/******************************************************************************
 * The way I want to do stuff (2005) rev. (Apr 20, 2007)
 * If you find an error, or improvement, let me know: dev at ajas dot us
 * This file is free for use
 *
 * functions:
 *  String.prototype.trim()      - remove whitespace from both ends of Str
 *  parseQueryString(String)     - querystring to associative array
 *  arrayDump(Array[,String])    - [recusive] array to pre-text
 *  cancelBubble(Event)          - stop event propagation
 *  mouseCoords(Event)           - return coords of mouse event
 *  getFormValues(Form)          - returns form values as querystring
 *  arrayToTable(Array[, String])- [recusive] array to key-value table
 *****************************************************************************/

if(!ajas)var ajas={};
if(!ajas.util)ajas.util={};

//add a trim function to JS Strings
//String.prototype.trim=function(){return this.replace(/^ +| +$/g,'');};
//trim: more aggressive, takes more forms of whitespace
String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,'');};

//add a reverse function to JS Strings
String.prototype.reverse=function(){return this.split('').reverse().join('');};


ajas.util.dpx=function(s) {
	return s.replace(/px$/,'');
}

ajas.util.copy=function(s){
	try{
		clipboardData.setData("Text", s);
	}catch(e){
		//credit for FF solution to http://www.jeffothy.com/weblog/clipboard-copy/
		var f='flashcopier';
		if(!document.getElementById(f)) {
			var o=document.createElement('div');
			o.id=f;
	//		o.style.display='none';
			document.body.appendChild(o);
//			o.innerHTML = '<input type="text"><iframe src="data:text/html;charset=utf-8;base64,'
//				+btoa('<embed src="data:application/x-shockwave-flash;base64,Q1dTB3kAAAB4nKtgYI1nYOBfwMDAw8jgzPT%2F%2F3975lAGBoYOdQYWhuSczIKk%2FMSiFIac1Lz0kgyG4MriktRchuLUEme41DQmBg4GGRDJ6Cc0l4lBAibCzsDOCDSJgwksyRwkzuAA5AIAd7oY%2Fw%3D%3D" FlashVars="code='+encodeURIComponent(s)+'"></embed>')+'"></iframe>';
		}
//		document.getElementById(f).innerHTML = '<embed src="data:application/x-shockwave-flash;base64,Q1dTB3kAAAB4nKtgYI1nYOBfwMDAw8jgzPT//3975lAGBoYOdQYWhuSczIKk/MSiFIac1Lz0kgyG4MriktRchuLUEme41DQmBg4GGRDJ6Cc0l4lBAibCzsDOCDSJgwksyRwkzuAA5AIAd7oY/w==" FlashVars="clipboard='+encodeURIComponent(s)+'" width="0" height="0" type="application/x-shockwave-flash"></embed>';
		document.getElementById(f).innerHTML = '<embed src="http://www.woktiny.net/wheel/_clipboard.swf" FlashVars="clipboard='+encodeURIComponent(s)+'" width="0" height="0" type="application/x-shockwave-flash"></embed>';
//		document.getElementById(f).innerHTML = '<embed src="Q1dTB3kAAAB4nKtgYI1nYOBfwMDAw8jgzPT%2F%2F3975lAGBoYOdQYWhuSczIKk%2FMSiFIac1Lz0kgyG4MriktRchuLUEme41DQmBg4GGRDJ6Cc0l4lBAibCzsDOCDSJgwksyRwkzuAA5AIAd7oY%2Fw%3D%3D" FlashVars="clipboard='+encodeURIComponent(s)+'" width="0" height="0" type="application/x-shockwave-flash"></embed>';
//		document.getElementById(f).contentWindow.document.body.innerHTML = '<input type="text"><embed src="data:application/x-shockwave-flash;base64,Q1dTB3kAAAB4nKtgYI1nYOBfwMDAw8jgzPT%2F%2F3975lAGBoYOdQYWhuSczIKk%2FMSiFIac1Lz0kgyG4MriktRchuLUEme41DQmBg4GGRDJ6Cc0l4lBAibCzsDOCDSJgwksyRwkzuAA5AIAd7oY%2Fw%3D%3D" FlashVars="code='+encodeURIComponent(s)+'"></embed>';
//Q1dTB3kAAAB4nKtgYI1nYOBfwMDAw8jgzPT%2F%2F3975lAGBoYOdQYWhuSczIKk%2FMSiFIac1Lz0kgyG4MriktRchuLUEme41DQmBg4GGRDJ6Cc0l4lBAibCzsDOCDSJgwksyRwkzuAA5AIAd7oY%2Fw%3D%3D
//TinyURL.com/2yh44h
	}
}		

/*
var aLpha={'A':'Alpha','B':'Bravo','C':'Charlie','D':'Delta','E':'Echo','F':'Foxtrot','G':'Golf','H':'Hotel','I':'India','J':'Juliet','K':'Kilo','L':'Lima','M':'Mike','N':'November','O':'Oscar','P':'Papa','Q':'Quebec','R':'Romeo','S':'Sierra','T':'Tango','U':'Uniform','V':'Victor','W':'Whiskey','X':'X-ray','Y':'Yankee','Z':'Zulu'};

var digits = '0123456789abcdefghijklmnopqrstuvwxyz';
function unparseNumber(i,r) {
	var s='';
	while (i>0){
		s=digits.charAt(i%r)+s;
		i=Math.floor(i/r);
	}
	return s;
}
function parseNumber(s,r) {
	var a=0,m=1,t=0;
	for (var i=s.length-1;i>=0;i--) {
		t=digits.indexOf(s.charAt(i));
		if(t>=r) return false;
		a+=m*t;
		m*=r;
	}
	return a;
}
function hex2ascii(sH) {
	var a=sH.split(' ');
	var sA='';
	for (var i in a) {
		sA+=String.fromCharCode(parseNumber(a[i],16));
	}
	return sA;
}
function binary2ascii(sB) {
	var a=sB.split(' ');
	var sA='';
	for (var i in a) {
		sA+=String.fromCharCode(parseNumber(a[i],2));
	}
	return sA;
}
function ascii2binary(sA) {
	var a=sA.split('');
	for (var i in a) {
		a[i]=pad(unparseNumber(a[i].charCodeAt(0),2),8,'0');
	}
	return a.join(' ');
}
function pad(s,l,p){
	while(s.length<l)s=p+s;
	return s;
}

*/

ajas.util.aROT13map={
	'a':'n','b':'o','c':'p','d':'q','e':'r','f':'s','g':'t','h':'u','i':'v','j':'w','k':'x','l':'y','m':'z',
	'n':'a','o':'b','p':'c','q':'d','r':'e','s':'f','t':'g','u':'h','v':'i','w':'j','x':'k','y':'l','z':'m',
	'A':'N','B':'O','C':'P','D':'Q','E':'R','F':'S','G':'T','H':'U','I':'V','J':'W','K':'X','L':'Y','M':'Z',
	'N':'A','O':'B','P':'C','Q':'D','R':'E','S':'F','T':'G','U':'H','V':'I','W':'J','X':'K','Y':'L','Z':'M'
	};
//16.92ms fastest, if you don't mind the map in memory
//ROT13 aided by array based map
ajas.util.rot13=function(s){
	var c='';
	for(var i=0; i<s.length;i++){
		c+=ajas.util.aROT13map[s.charAt(i)]||s.charAt(i);
	}
	return c;
}

//24.04ms string map, not bad, not great
//ROT13 aided by string based map
ajas.util.rot13_sm=function(s){
	var a='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
	var b='nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM';
	var c='';
	for(var i=0;i<s.length;i++){
		c+=a.charAt(b.indexOf(s.charAt(i)))||s.charAt(i);
	}
	return c;
}

//21.23ms classic form, not as fast as the array mapped
//ROT13 by traditional char value checking
ajas.util.rot13_if=function(s){
	var c='';
	var b;
	for(var i=0; i<s.length;i++){
		b=s.charCodeAt(i);
		if(((b>64)&&(b<78))||((b>96)&&(b<110))){
			b+=13;
		} else if (((b>77)&&(b<91))||((b>109)&&(b<123))) {
			b-=13;
		}
		c+=String.fromCharCode(b);
	}
	return c;
}


//40.86ms beautiful, but slow
//ROT13 aided by regular expression replace.
ajas.util.rot13_re=function(s) {
	return s.replace(/[a-zA-Z]/g, function(c){
		return String.fromCharCode((c <= 'Z' ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26);
	});
}



//Return an array of counts for each letter in a string, useful for pangram checking
ajas.util.alphaCount=function(ref) {
	var aCounts={'a':0,'b':0,'c':0,'d':0,'e':0,'f':0,'g':0,'h':0,'i':0,'j':0,'k':0,'l':0,'m':0,'n':0,'o':0,'p':0,'q':0,'r':0,'s':0,'t':0,'u':0,'v':0,'w':0,'x':0,'y':0,'z':0};
	var s=ref.value;
	for (var i=0;i<s.length;i++) {
		var j=s.charAt(i).toLowerCase();
		if(document.getElementById(j)) ++aCounts[j];
	}
	return aCounts;
}


//takes a basic ?key=val&key2=val2 string and returns an associative array
ajas.util.parseQueryString=function(sQueryString) {
	sQueryString = sQueryString.replace(/^\?/, '');//toss leading ?
	if (sQueryString.length == 0) return;
	aParams=new Array();
	sQueryString = sQueryString.replace(/\+/g, ' ');//interpret '+' as space
	var aPairs = sQueryString.split('&');
	for(var i in aPairs) {
		var pair = aPairs[i].split('=',2);
		aParams[unescape(pair[0])]=pair.length==2?unescape(pair[1]):'';
	}
	return aParams;
}

//JS escape that also handles + -> %2b
ajas.util.escapePlus=function(s){
	return escape(s).replace(/\053/g,'%2b');
}


//takes an associative array and returns  a basic ?key=val&key2=val2 string
ajas.util.buildQueryString=function(aParams) {
	var a=[];
	for(var i in aParams) {
		a.push(ajas.util.escapePlus(i)+'='+ajas.util.escapePlus(aParams[i]));
	}
	return a.join('&');
}

//takes an array and gens some printable text, better put output in <pre>
ajas.util.arrayDump=function(aRef, sPre) {
	if(arguments.length == 1) sPre='\n';
	var sTEXT = 'Array {';
	var sPreN = sPre+'  ';
	for(var i in aRef){
		if (typeof(aRef[i]) == 'object' && typeof(aRef[i]) != 'string') {
			sTEXT += ''+sPreN+i+" => "+ajas.util.arrayDump(aRef[i],sPreN);
		} else {
			sTEXT += ''+sPreN+i+" => "+aRef[i];
		}  
	}
	return sTEXT+''+sPre+'}';
}

//takes an array and gens a PHP definition
ajas.util.arrayToPhp=function(aRef) {
	var a=[];
	for(var i in aRef){
		if (typeof(aRef[i]) == 'object' && typeof(aRef[i]) != 'string') {
			a.push("'"+i+"' => "+ajas.util.arrayToPhp(aRef[i]));
		} else {
			a.push("'"+i+"' => '"+aRef[i]+"'");
		}  
	}
	return 'array('+a.join(',')+')';
}
//takes an array and gens some crude tables
ajas.util.arrayToTable=function(aRef, sPre) {
	if(arguments.length == 1) sPre='';
	var sTEXT = '<table border=1 style=\"border:1px solid black;border-collapse:collapse;\">';
	for(var i in aRef){
		if (typeof(aRef[i]) == 'object' && typeof(aRef[i]) != 'string') {
			sTEXT += '<tr><td>'+i+'</td><td>'+ajas.util.arrayToTable(aRef[i],sPreN)+'</td></tr>';
		} else {
			sTEXT += '<tr><td>'+i+'</td><td>'+aRef[i]+'</td></tr>';
		}  
	}
	return sTEXT+'</table>';
}

// simple object for storing immutable (self)references
ajas.util.store=function(){
	var private={
		list:{},
		i:0
	};
	var public={
		add:function(o){
			private.list[private.i]=o;
			return private.i++;
		},
		get:function(i){
			return private.list[i];
		}
	};
	return public;
}();