/* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + *
   Day Parting Sliders
   Simon Champion. Copyright Skycom Ltd.

   This program allows users to set up their phone numbers so that their calls
   are redirected to different numbers at different times of day. They use a
   graphical slider control to build up their settings, which has full drag &
   drop capabilities.

   The program makes use of Javascript, CSS and XMLHTTPRequest, so it requires an
   up-to-date browser. It has been tested, and works, on: MSIE 6 (Windows XP),
   Firefox 2.0.0.6 (Win XP & Linux), Opera 9 (Linux), Konqueror 3.5.6 (Linux).
   However, there are a couple of browser-specific differences that the program
   has to take into account, particularly with MSIE.
   (1) Two different methods were written for displaying the background pattern in
       the slider bars. We'll call them modes "0" and "1". Mode 1 works in all
       browsers that support opacity (ie all tested except Opera); Mode 0 works
       in all browsers, and looks better than mode 1, but resizing of segments
       is *very* slow in MSIE in this mode. Therefore we prefer to use mode 0,
       but revert to mode 1 under MSIE.
   (2) Highlighting text is disabled to prevent the drag+drop functions from
       selecting chunks of the page when you drag, as this makes it very distracting
       to use. To disable highlighting in MSIE, a javascript event handler is
       required, whereas Firefox uses CSS. Opera and Konqueror do not support
       disabling of highlighting. Users of these browsers will just have to live
       with it.
   (3) XMLHTTPRequest works differently under MSIE compared to other browsers.
       See api-lite.php.js.
   Of these, only (3) is a serious issue: the first two are simply attempts to
   make it look as good as possible under every browser; the third directly affects
   crucial functionality. Fortunately though, the issue is well documented, as
   all AJAX web sites have to deal with it.

   For testing purposes, or curiosity, setting a url parameter of "slidermode=1"
   or "slidermode=0" changes the method the program uses to display the sliders,
   and allows you to see the two modes described in (2) above.
   The difference can be seen when the sliders are moved. In the absence of this
   parameter (ie normal usage), the program will use the mode that best suits the
   particular browser (ie mode 0 looks better, but is too slow under MSIE).
   "slidermode=2" (solid colours) is also available, but is deprecated.

   Also note, that in order to work on all browsers, the main page requires the
   doctype to be specified. It has been tested with the html/loose.dtd doctype,
   and should work with strict.dtd as well, but does not work on all browsers
   without it (especially MSIE).
 * + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + */

//used for alt text and title attribute, each in two places, so defined globally rather than repeating them all the time.
var G_AltText=new Array;
G_AltText['suspended']="Number is suspended: Please contact us to re-enable it.";
G_AltText['nowhere']="Number inactive. Callers will hear an engaged tone.";
G_AltText['number']="Configure with a single destination number (eg route to my home phone)";
G_AltText['dayparting']="Configure with a time-based system (eg route to my mobile after office hours)";
G_AltText['routeplan']="Configure with a single route plan (eg divert call after 15 seconds)";
G_AltText['fax2email']="Configured as a fax to email service.";
G_AltText['externally-routed']="Special customised configuration.";
G_AltText['2stageIDA']="Configured with 2-Stage Indirect Access.";
G_AltText['customer']="Allocate to one of your customers.";
G_AltText['sip']="Configure with a SIP (VOIP) address.";
G_AltText['originbased']="Origin-based routing. (caller location)";
G_AltText['voicemail']="Divert number directly to a voicemail box";

if(!window.G_imgdir) {var G_imgdir='';}

var query=QueryStringToArray(location.search);

var IamExplorer=(navigator.appName == "Microsoft Internet Explorer");
var IamOpera=(navigator.userAgent.match("Opera"));	//Opera mostly pretends to be Explorer (so IamExplorer will also be set), which is fine for most of the browser-specific stuff here, but for slider background effects, we have to be more specific, because Opera doesen't support opacity yet. Note: if the user has spoofed IE with their user agent string, then they'll get the IE effect. Don't know any other way to tell the difference.
var IamKonqueror=(navigator.appName == "Konqueror");	//Konq doesn't do transparency yet either.

var SliderMode=(IamExplorer&&!IamOpera)?1:0;
if(query.slidermode) { SliderMode=parseInt(query.slidermode); }

document.onmousemove = MouseMoved;
document.onselectstart=new Function("if(menuinfo.num==0 && colourdragmode==0 && !adjustmode) {return true;} else {return false;}");

var G_dpid=0;

var debug=0;
var posX = 0;
var posY = 0;
var startingX = 0;
var gimmestart=false;
var adjustmode = 0;
var helpmode="";
var colourdragmode=false;
var colourdrag=new Array;
var msslider=(SliderMode!=2?'msslider ':'');
var pnum=(SliderMode>0?msslider+'pnum':'fnum');
var pnum2=(!IamOpera&&!IamKonqueror?msslider+'pnum':'fnum');

var item=new Array;
var next=new Array;
var menuinfo=new Array;

var scalepos=new Array;
scalepos[0]=0;
scalepos[1]=3;
scalepos[2]=7;
scalepos[3]=10;
scalepos[4]=14;
scalepos[5]=18;
scalepos[6]=21;
scalepos[7]=25;
scalepos[8]=29;
scalepos[9]=32;
scalepos[10]=36;
scalepos[11]=40;
scalepos[12]=43;
scalepos[13]=47;
scalepos[14]=51;
scalepos[15]=54;
scalepos[16]=58;
scalepos[17]=61;
scalepos[18]=65;
scalepos[19]=69;
scalepos[20]=72;
scalepos[21]=76;
scalepos[22]=80;
scalepos[23]=83;
scalepos[24]=87;
scalepos[25]=91;
scalepos[26]=94;
scalepos[27]=98;
scalepos[28]=102;
scalepos[29]=105;
scalepos[30]=109;
scalepos[31]=113;
scalepos[32]=116;
scalepos[33]=120;
scalepos[34]=123;
scalepos[35]=127;
scalepos[36]=131;
scalepos[37]=134;
scalepos[38]=138;
scalepos[39]=142;
scalepos[40]=145;
scalepos[41]=149;
scalepos[42]=153;
scalepos[43]=156;
scalepos[44]=160;
scalepos[45]=164;
scalepos[46]=167;
scalepos[47]=171;
scalepos[48]=174;
scalepos[49]=178;
scalepos[50]=182;
scalepos[51]=185;
scalepos[52]=189;
scalepos[53]=193;
scalepos[54]=196;
scalepos[55]=200;
scalepos[56]=204;
scalepos[57]=207;
scalepos[58]=211;
scalepos[59]=215;
scalepos[60]=218;
scalepos[61]=222;
scalepos[62]=226;
scalepos[63]=229;
scalepos[64]=233;
scalepos[65]=236;
scalepos[66]=240;
scalepos[67]=244;
scalepos[68]=247;
scalepos[69]=251;
scalepos[70]=255;
scalepos[71]=258;
scalepos[72]=262;
scalepos[73]=266;
scalepos[74]=269;
scalepos[75]=273;
scalepos[76]=277;
scalepos[77]=280;
scalepos[78]=284;
scalepos[79]=288;
scalepos[80]=291;
scalepos[81]=295;
scalepos[82]=298;
scalepos[83]=302;
scalepos[84]=306;
scalepos[85]=309;
scalepos[86]=313;
scalepos[87]=317;
scalepos[88]=320;
scalepos[89]=324;
scalepos[90]=328;
scalepos[91]=331;
scalepos[92]=335;
scalepos[93]=339;
scalepos[94]=342;
scalepos[95]=346;
scalepos[96]=349;
scalepos[97]=353;
scalepos[98]=357;
scalepos[99]=360;
scalepos[100]=364;

var numtypeflag=new Array;
numtypeflag[0]=0;
numtypeflag[1]=0;
numtypeflag[2]=0;
numtypeflag[3]=0;
numtypeflag[4]=0;
numtypeflag[5]=0;
numtypeflag[6]=0;
numtypeflag[7]=0;
numtypeflag[8]=0;
numtypeflag[9]=0;

function MouseMoved(e) {
	CurrPos(e);
	if(gimmestart) {startingX=posX; gimmestart=false;}

	if(colourdragmode) {
		document.getElementById("minicolourblock").style.left=(posX+7)+"px";
		document.getElementById("minicolourblock").style.top=(posY+7)+"px";

	}

	if (adjustmode){ 	// we need to resize something...
		if(posX!=startingX){
			var movepx=startingX-posX;
			item['w']=parseInt(item['o'].style.width,10);
			next['w']=parseInt(next['o'].style.width,10);
			item['nw']=item['w']-movepx;
			next['nw']=next['w']+movepx;
			if(item['rw']==0) {item['rs']=dp_data[item['d']][item['p']]['end_seg']; item['rw']=item['w'];} else {item['rw']-=movepx;}	//'r' is the relative width, from the initial starting width.
			if(item['nw']>2 && next['nw']>2) {
				//Resize the divs according to the mouse position...
				item['o'].style.width=(item['w']-movepx)+"px";
				next['o'].style.width=(next['w']+movepx)+"px";
				startingX=posX;

				var totwidth=0;
				for(var count=1; count<=item['p']; count++) {
					var obj=document.getElementById(item['dc']+"_"+LeadingZeros(count,3));
					totwidth+=parseInt(obj.style.width)+2+1;
					if(count>1) {totwidth+=2;}
				}
				var newseg=FindSeg(totwidth);
				dp_data[item['d']][item['p']]['end_seg']=newseg;

				//Sanity checking to stop the block from overlapping...
				if(dp_data[item['d']][item['p']]['end_seg']>=96) {dp_data[item['d']][item['p']]['end_seg']=95;}
				if(dp_data[item['d']][item['p']]['end_seg']<=1)  {dp_data[item['d']][item['p']]['end_seg']=1;}
				if(dp_data[item['d']][item['p']]['end_seg']>=dp_data[next['d']][next['p']]['end_seg']) {dp_data[item['d']][item['p']]['end_seg']=dp_data[next['d']][next['p']]['end_seg']-1;}
				if(dp_data[item['d']][item['p']]['end_seg']<=dp_data[item['d']][item['p']]['start_seg']) {dp_data[item['d']][item['p']]['end_seg']=dp_data[item['d']][item['p']]['start_seg']+1;}

				//Update all the affected segs and times so both blocks match...
				dp_data[item['d']][item['p']]['end_time']=SegToTime(dp_data[item['d']][item['p']]['end_seg']);
				dp_data[next['d']][next['p']]['start_seg']=dp_data[item['d']][item['p']]['end_seg'];
				dp_data[next['d']][next['p']]['start_time']=SegToTime(dp_data[next['d']][next['p']]['start_seg']);

				//Display the time we're adjusting in the help box.
				document.getElementById("floatinghelp").innerHTML=dp_data[item['d']][item['p']]['end_time'];
			}
		}
	}
	ShowHelp();
	return true;
}

function CurrPos(e) {
	if(!IamExplorer){
		posX = e.pageX;
		posY = e.pageY;
	} else {
		posX = window.event.clientX + document.documentElement.scrollLeft;
		posY = window.event.clientY + document.documentElement.scrollTop;
	}
	if (posX<=0) {posX=0;}
	if (posY<=0) {posY=0;}
}

function FindSeg(width) {
	for(var count=1;count<96;count++) {
		var aveup=Math.round((scalepos[count]+scalepos[count+1])/2);
		var avedn=Math.round((scalepos[count]+scalepos[count-1])/2);
		if(width>=avedn && width<=aveup) {return(count);}
	}
	return -5;	//arbitrary error code. Doesn't really matter what it is, as long as it's a number, outside the allowed range (1-95)
}

function DropMode(day,num,daynum) {
	//this is called by onmouseup event on the time seg blocks
	//used for dropping new colours onto time segments.
	document.getElementById("saveinfo").innerHTML="";

	if(!colourdrag.day) {
		OptsMenu(0,"",0);
	}

	if(colourdragmode) {
		//Turning off dragmode while colourdragmode is set?
		if(colourdrag.sec && colourdrag.seg) {
			if(dp_data[colourdrag.sec][colourdrag.seg]['id']) {
				//Change the colour of the currently selected segment...
				var lzro=LeadingZeros(colourdrag.key,3);
				dp_data[colourdrag.sec][colourdrag.seg]['number']=GetDPNumDesc(colourdrag.key);
				dp_data[colourdrag.sec][colourdrag.seg]['dp_number_id']=dp_numlist[colourdrag.key]['id'];
				dp_data[colourdrag.sec][colourdrag.seg]['dp_colour_id']=colourdrag.key;
				colourdrag.pgo.className='blockdiv '+pnum+lzro;
				if(colourdrag.lbo) {colourdrag.lbo.className=colourdrag.lbo.className.replace(/num\d\d\d/,'num'+lzro);}
				if(colourdrag.rbo) {colourdrag.rbo.className=colourdrag.rbo.className.replace(/num\d\d\d/,'num'+lzro);}
			}
		}
		DragColour(0,0,"");	//and finally, turn colourdragmode off so it doesn't affect us any more.
	}
}

function DragMode(mode,day,num,daynum) {
	//this is called by onmousedown event on the block sizers, or onmouseup event anywhere on the page.
	document.getElementById("saveinfo").innerHTML="";

	if(!colourdrag.day || mode) {
		OptsMenu(0,"",0);
	}

	if(!mode) {
		DragColour(0,0,"");
	}

	gimmestart=true;
	adjustmode=mode;
	if(!mode && item['d']) {
		//turning off dragmode? Snap the moved line to the grid.
		var maxsects=dp_data[item['d']].length-1;

		var thiswidth=(scalepos[dp_data[item['d']][item['p']]['end_seg']]-scalepos[dp_data[item['d']][item['p']]['start_seg']])-1;
		thiswidth-=2*((item['p']==1||item['p']==maxsects)?1:2);
		if(item['p']==1||item['p']==maxsects) { thiswidth++; }

		var actualsize=parseInt(item['o'].style.width,10);
		var actualsize2=parseInt(next['o'].style.width,10);

		var snapdiff=thiswidth-actualsize;

		item['o'].style.width=(actualsize+snapdiff)+"px";
		next['o'].style.width=(actualsize2-snapdiff)+"px";

		item['d']=0;
	}
	item['d']=daynum;
	next['d']=daynum;
	item['dc']=day;
	next['dc']=day;
	item['p']=num;
	next['p']=parseInt(num)+1;
	item['rw']=0;
	item['o']=document.getElementById(day+"_"+LeadingZeros(item['p'],3));
	next['o']=document.getElementById(day+"_"+LeadingZeros(next['p'],3));

	helpmode=mode?"dragtime":"";
	if(helpmode) {document.getElementById("floatinghelp").innerHTML=dp_data[item['d']][item['p']]['end_time'];}
}

function DragColour(mode,key,num) {
	//Turn on colour drag mode -- allow user to drag a mini colour block onto the main table.
	if(key>0 && document.getElementById("term-number-"+LeadingZeros(key,3)).value=="" && document.getElementById("sel-routeplan-"+LeadingZeros(key,3)).value==0 && document.getElementById("sel-voicemail-"+LeadingZeros(key,3)).value==0) {mode=0;}

	var obj=document.getElementById("minicolourblock");
	if(!mode) {
		colourdragmode=false;
		obj.className='minicolourblock dp_hide';
	} else {
		OptsMenu(0,"",0);
		colourdragmode=true;
		obj.className='minicolourblock dp_show '+pnum2+LeadingZeros(key,3);
		obj.style.left=(posX+7)+"px";
		obj.style.top=(posY+7)+"px";
		colourdrag.key=key;
		colourdrag.num=num;
	}
}

function BlockTime(sec,seg,day) {
	//this is called by onmouseover event of the time seg blocks.
	if(helpmode!="dragtime") {	//don't override the dragtime helper.
		if(sec==0) {
			helpmode="";
		} else {
			helpmode="blocktime";
			document.getElementById("floatinghelp").innerHTML=DivTimeTitle(sec,seg)+"<br />"+dp_data[sec][seg]['number'];
		}
	}

	//keep track of the colour drag mode settings here too, since it needs to be triggered by the same event.
	if(sec) {
		colourdrag.pgo=document.getElementById(day+"_"+LeadingZeros(seg,3));
		colourdrag.sec=sec;
		colourdrag.seg=seg;
		colourdrag.day=day;

		//track the objects for the left+right drag bars
		var lb="l_drag_"+day+"_"+LeadingZeros(seg-1,3);
		var rb="r_drag_"+day+"_"+LeadingZeros(seg,3);
		if(document.getElementById(lb)) {colourdrag.lbo=document.getElementById(lb);} else {colourdrag.lbo=document.getElementById(rb);}
		if(document.getElementById(rb)) {colourdrag.rbo=document.getElementById(rb);} else {colourdrag.rbo=document.getElementById(lb);}
	} else {
		colourdrag.sec=0;
		colourdrag.seg=0;
		colourdrag.day=0;
	}

	ShowHelp();
}

function SetHelpMode(mode,key) {
	helpmode=mode;
	switch(mode) {
		case "colourblock":
			if(key==0 || document.getElementById("term-number-"+LeadingZeros(key,3)).value!="" || document.getElementById("sel-routeplan-"+LeadingZeros(key,3)).value>0 || document.getElementById("sel-voicemail-"+LeadingZeros(key,3)).value>0) {
				document.getElementById("floatinghelp").innerHTML="Drag colour block onto day sections to set redirect numbers.";
			} else {
				helpmode="";
			}
			break;
	}
	ShowHelp();
}

function OptsMenu(num,day,seg) {
	var obj=document.getElementById("floatingmenu");
	if(!num) {
		obj.className='menublock dp_hide';
		//they might have let go of the menu while one of the options was highlighted, so blank the background colours of all the options.
		for(var count=1;count<obj.childNodes.length;count++) { if(obj.childNodes[count].style) { obj.childNodes[count].style.backgroundColor=""; } }
		menuinfo.num=0;
		menuinfo.day="";
		menuinfo.seg=0;
	} else {
		obj.className='menublock dp_show';
		obj.style.left=(posX-2)+"px";
		obj.style.top=(posY+8)+"px";
		menuinfo.num=num;
		menuinfo.day=day;
		menuinfo.seg=seg;
	}
	ShowHelp();
}

function MenuSplit() {
	//if the range is less than two segs, then it can't be split.
	if(dp_data[menuinfo.num][menuinfo.seg]['end_seg']-dp_data[menuinfo.num][menuinfo.seg]['start_seg']<4) { return; }

	//first, find the mid-point of the range.
	var midpoint=Math.round((parseInt(dp_data[menuinfo.num][menuinfo.seg]['start_seg'])+parseInt(dp_data[menuinfo.num][menuinfo.seg]['end_seg']))/2);
	var midtime=SegToTime(midpoint);

	//insert an extra block, identical to the one we're splitting.
	var temparr=new Array;
	for (var item in dp_data[menuinfo.num][menuinfo.seg]) { temparr[item]=dp_data[menuinfo.num][menuinfo.seg][item];}
	dp_data[menuinfo.num].splice(menuinfo.seg,0,temparr);

	//now adjust the two so that their start/end times fall in the middle of the existing range.
	dp_data[menuinfo.num][menuinfo.seg]['end_time']=midtime;
	dp_data[menuinfo.num][menuinfo.seg]['end_seg']=midpoint;
	dp_data[menuinfo.num][menuinfo.seg]['max_seg']=dp_data[menuinfo.num][menuinfo.seg+1]['end_time'];
	dp_data[menuinfo.num][menuinfo.seg+1]['start_time']=midtime;
	dp_data[menuinfo.num][menuinfo.seg+1]['start_seg']=midpoint;
	DayDiv(menuinfo.day,menuinfo.num);	//easiest just to redraw the day's layout from scratch.
}

function MenuMergeLeft() {
	if(menuinfo.seg>1) {		//can't left-merge the first one!
		//copy the start times across from the item being removed into the one that's being kept, then remove the obsolete item from the array.
		dp_data[menuinfo.num][menuinfo.seg]['start_time']=dp_data[menuinfo.num][menuinfo.seg-1]['start_time'];
		dp_data[menuinfo.num][menuinfo.seg]['start_seg']=dp_data[menuinfo.num][menuinfo.seg-1]['start_seg'];
		dp_data[menuinfo.num].splice(menuinfo.seg-1,1);
		DayDiv(menuinfo.day,menuinfo.num);	//easiest just to redraw the day's layout from scratch.
	}
}

function MenuMergeRight() {
	if(menuinfo.seg<dp_data[menuinfo.num].length-1) {	//can't right-merge the last one!
		//copy the end times across from the item being removed into the one that's being kept, then remove the obsolete item from the array.
		dp_data[menuinfo.num][menuinfo.seg]['end_time']=dp_data[menuinfo.num][menuinfo.seg+1]['end_time'];
		dp_data[menuinfo.num][menuinfo.seg]['end_seg']=dp_data[menuinfo.num][menuinfo.seg+1]['end_seg'];
		dp_data[menuinfo.num][menuinfo.seg]['max_time']=dp_data[menuinfo.num][menuinfo.seg+1]['max_time'];
		dp_data[menuinfo.num].splice(menuinfo.seg+1,1);
		DayDiv(menuinfo.day,menuinfo.num);	//easiest just to redraw the day's layout from scratch.
	}
}

function ShowHelp() {
	var helpobj=document.getElementById("floatinghelp");
	if(!helpobj) {
		return;
	}
	if(helpmode && document.getElementById("floatingmenu").className!='menublock dp_show') {
		helpobj.className='helpblock dp_show';
		helpobj.style.left=(posX+12)+"px";
		helpobj.style.top=(posY+12)+"px";
	} else {
		helpobj.className='helpblock dp_hide';
	}
}

//Construct a block for a day, using the dp_data[] array.
function DayDiv(day,dp_num) {
	var maxsects=dp_data[dp_num].length-1;
	var output="";

	for(var count in dp_data[dp_num]) {
		if(!dp_data[dp_num][count]['dp_colour_id']) {dp_data[dp_num][count]['dp_colour_id']=WhichNum(dp_data[dp_num][count]['dp_number_id']);}
		var numid=LeadingZeros(dp_data[dp_num][count]['dp_colour_id'],3);
		var thiswidth=(scalepos[dp_data[dp_num][count]['end_seg']]-scalepos[dp_data[dp_num][count]['start_seg']])-1;
 		thiswidth-=(2)*((count==1||count==maxsects)?1:2);
		if(count==1&&count==maxsects) { thiswidth+=2+1; }	//special case when only one block, so no sizers.
		if(count==1||count==maxsects) { thiswidth++; }				//special case when we're at either the left or right edge.

		var prtcount=LeadingZeros(count,3);
		if(count>1) {output+=Sizer_Div(dp_num,day,count-1,numid,0)+"\n";}
		output+="<div id='"+day+"_"+prtcount+"' class='blockdiv "+pnum+numid+"' style='width:"+thiswidth+"px;' onmouseover='BlockTime("+dp_num+","+count+",\""+day+"\");' onmouseout='BlockTime(0,0,\"\");' onmousedown='OptsMenu("+dp_num+",\""+day+"\","+count+");' onmouseup='DropMode(\""+day+"\","+count+","+dp_num+");'></div>\n";
		if(count<maxsects) {output+=Sizer_Div(dp_num,day,count,numid,1)+"\n";}
	}

	document.getElementById("maindiv_"+day).innerHTML=output;
}

function SegToTime(seg) {
	var hh=LeadingZeros(Math.floor(seg/4),2);
	var mm=LeadingZeros((seg%4)*15,2);
	return hh+":"+mm;
}

function DivTimeTitle(dp_num,seg) {
	return dp_data[dp_num][seg]['start_time']+" to "+dp_data[dp_num][seg]['end_time'];
}

function Sizer_Div(dp_num,day,num,numid,mode) {
	var snum=LeadingZeros(num,3);
	var lr=(mode==0?"l":"r");
	var sclass="";
	if(mode==1)	{sclass ='sizeredge';}
	sclass+=' sizerdiv';
	sclass+=' '+pnum+LeadingZeros(numid,3);
	var over="onmouseover='BlockTime("+dp_num+","+num+",\""+day+"\");'";
	var mout="onmouseout='BlockTime(0,0,\"\");'";
	var drag="onmousedown='DragMode(1,\""+day+"\","+num+","+dp_num+");'"
	var drop="onmouseup='DropMode(\""+day+"\","+(num-mode)+","+dp_num+");'";

	var td_sizer ="<div id='"+lr+"_drag_"+day+"_"+snum+"' class='"+sclass+"' "+drag+" "+drop+" "+over+" "+mout+"></div>\n";

	return td_sizer;
}

function WhichNum(numid) {
	for(key in dp_numlist) {
		if(dp_numlist[key]['id']==numid) {return key;}
	}
	return 0;	//just in case we didn't find one.
}

function PutNumbers() {
	var numlistlines=0; for(var tst in dp_numlist) {numlistlines++;}
	if(numlistlines<=9) {
		dp_numlist[numlistlines]=new Array();
		dp_numlist[numlistlines]['id']=0;
		dp_numlist[numlistlines]['number']='';
		dp_numlist[numlistlines]['rpid']=0;
		dp_numlist[numlistlines]['mbid']=0;
	}
	var output="<br />";
	for(key in dp_numlist) {
		output+=NumInput(key,dp_numlist[key]);
	}
	document.getElementById("numblock").innerHTML=output;
	for(key in dp_numlist) {
		if(dp_numlist[key]['rpid']>0) {
			document.getElementById("sel-routeplan-"+LeadingZeros(key,3)).value=dp_numlist[key]['rpid'];
		}
		if(dp_numlist[key]['mbid']>0) {
			document.getElementById("sel-voicemail-"+LeadingZeros(key,3)).value=dp_numlist[key]['mbid'];
		}
	}
}

function NumInput(key,numdata) {
	var thisbtns=new Array();
	thisbtns['number']=true;
	thisbtns['routeplan']=true;
	thisbtns['voicemail']=true;

	var okey=key;
	key=LeadingZeros(key,3);
	output="<div id='numinput_"+key+"'>";
	output+="<div id='drag_"+key+"' class='dp_nosel numcolour "+pnum2+key+"' onmouseover='SetHelpMode(\"colourblock\","+key+");' onmouseout='SetHelpMode(\"\",0);' onmousedown='DragColour(1,"+okey+",\""+numdata['number']+"\");'></div>";
	if(okey!=0) {
		var activebtn='number';
		if(numdata['rpid']>0) {activebtn='routeplan';}
		if(numdata['mbid']>0) {activebtn='voicemail';}

		output+= "<div align='left' style='padding-left:50px;'>"
			+"<table><tr><td valign='top'>";

		for(var btnkey in thisbtns) {output+=DrawBtn(btnkey,key,activebtn);}

		output+="</td><td valign='top'>";

		if(thisbtns['sip']) {output+=RoutingField('sip',okey,activebtn,'','input',numdata['sipaddr']);}
		if(thisbtns['number']) {output+=RoutingField('number',okey,activebtn,'','input',numdata['number']);}
		if(thisbtns['routeplan']) {output+=RoutingField('routeplan',okey,activebtn,'','select',G_RPselect);}
		if(thisbtns['originbased']) {output+=RoutingField('originbased',okey,activebtn,'','select',G_OBselect);}
		if(thisbtns['voicemail']) {output+=RoutingField('voicemail',okey,activebtn,'','select',G_MBselect);}

		output+= "</td></tr></table>"
			 +"</div>";
	} else {
		output+="<span align='left' style='margin-left:10px;'><b>Inactive</b></span>";
	}
	output+="</div><br />\n";
	return output;
}

function RoutingField(ftype,brow,activebtn,flddesc,itype,opts) {
	var trigger="ChangeNum(\""+ftype+"\",\""+brow+"\",this.value);";
	brow=LeadingZeros(brow,3);
	var fldcode='';
	switch(itype) {
		case 'select' :
			fldcode="<select id='sel-"+ftype+"-"+brow+"' class='cartForm' style='font-size:10px; width:15em; height:17px; vertical-align: middle;' onchange='"+trigger+"' >"+opts+"</select>";
			break;
		case 'input' :
			if(activebtn!=ftype) {opts='';}
			fldcode="<input type='text' class='cartForm' style='vertical-align:middle;' size='20' name='term-"+ftype+"-"+brow+"' id='term-"+ftype+"-"+brow+"' value='"+opts+"' onchange='"+trigger+"' />";
			break;
		case 'saveonly' :
			fldcode=opts;
			break;
		default:
			break;
	}
	var outstr="<span id='popvalue-"+ftype+"-"+brow+"' class='"+(activebtn==ftype?'showblock':'hideblock')+"'>";
	if(fldcode)  {outstr+="<span class='termopt_desc'>"+flddesc+"</span><div class='termopt_field'>"+fldcode+"</div>";}
		else {outstr+="<span class='termopt_info'>"+flddesc+"</span>";}
	outstr+="</span>";
	return outstr;
}

function DrawBtn(inname,brow,activebtn) {
	//inname = the name of this button (eg 'routeplan').
	//brow = the row identifier (on number management page, this would be 0845 number, etc; here it is the dpnumID.
	//activebtn = the name of the active button in this set, so we know whether to show the highlighted one or not.
	var gfxname=G_imgdir+"images/mgt/mgt-"+inname;
	var stext="alt='"+G_AltText[inname]+"' title='"+G_AltText[inname]+"'";
	var script="onmouseover='this.src=\""+gfxname+"-b.gif\";' onmouseout='this.src=\""+gfxname+"-c.gif\";' onclick='NumTermSwitch(\""+inname+"\",\""+brow+"\");'";

	var outstr='';

	outstr+= "<img src='"+gfxname+"-a.gif' "+stext+" id='term-"+inname+"-a_"+brow+"' class='termbtn_active "+(activebtn==inname?"showblock":"hideblock")+"' />"
		+"<img src='"+gfxname+"-c.gif' "+stext+" id='term-"+inname+"-b_"+brow+"' class='termbtn_ready " +(activebtn!=inname?"showblock":"hideblock")+"' "+script+" />";
	return outstr;
}

function NumTermSwitch(termtype,number) {
	for(var key in G_AltText) {
		NumTermSwitch2(key,termtype,number);
	}
}
function NumTermSwitch2(key,termtype,number) {
	var ta=document.getElementById("term-"+key+"-a_"+number);	//this is the highlighted toggle image for this termination type.
	var tb=document.getElementById("term-"+key+"-b_"+number);	//this is the greyed toggle button for this termination type.
	var pv=document.getElementById("popvalue-"+key+"-"+number);	//this is the input block for this termination type.
	//need to check that they all exist, as some termination types may be disabled.
	if(ta) { ta.className="termbtn_active "+(termtype==key?"showblock":"hideblock"); }
	if(tb) {
		tb.className="termbtn_ready "+(termtype==key?"hideblock":"showblock");
		tb.src=G_imgdir+"images/mgt/mgt-"+key+"-c.gif";	//simulate a mouseout event, so we don't leave highlighted images behind.
	}
	if(pv) { pv.className=((termtype==key)?"showblock":"hideblock"); }
}

function ChangeNum(ftype,key,value) {
	if(key>=dp_numlist.length) {
		dp_numlist.length=key+1;
		dp_numlist[key]=new Array();
		dp_numlist[key]['id']=0;
		dp_numlist[key]['number']='';
		dp_numlist[key]['rpid']=0;
		dp_numlist[key]['mbid']=0;
	}

	if(ftype=='number') {
		if(value.length>0) {
			if(!IsValidPhonenum(value,true,false)) {
				alert("Error: The number you entered does not appear to be a valid phone number.");
				DragMode(0,"","");	//fire the drag mode off event, to prevent the mode being left hanging when the alert box is displayed.
				document.getElementById("term-number-"+LeadingZeros(key,3)).focus();
				DragMode(0,"","");
				return false;
			}
		} else {
			DragMode(0,"","");	//fire the drag mode off event, to prevent the mode being left hanging when the msgbox is displayed.
			var yes=confirm("Warning: Unsetting this number will result in all time blocks that use it being set to inactive when you save. Are you sure?");
			if(!yes) {
				document.getElementById("term-number-"+LeadingZeros(key,3)).value=(dp_numlist[key]['number']?dp_numlist[key]['number']:"");
				document.getElementById("term-number-"+LeadingZeros(key,3)).focus();
				return false;
			}
		}
	} else {
		//routeplans or mailboxes -- no validation required: if the ID is available, then it's okay to have it.
	}

	dp_numlist[key]['number']=''; dp_numlist[key]['rpid']=''; dp_numlist[key]['mbid']='';
	switch(ftype) {
		case 'number' :
			dp_numlist[key]['number']=value;	//update the number array
			break;
		case 'routeplan' :
			dp_numlist[key]['rpid']=value;
			break;
		case 'voicemail' :
			dp_numlist[key]['mbid']=value;
			break;
		default :
			alert("Invalid routing type specified -- "+ftype);
			break;
	}
	var numlistlines=0; for(var tst in dp_numlist) {numlistlines++;}	//for some reason dp_numlist.length was giving weird results, so use lines counter instead.
	if(key==(numlistlines-1) && numlistlines<=9) {		//if edited the blank number at the end of the list, it will add a new one to the table, as long as they don't exceed the max num of nums.
		PutNumbers();
		document.getElementById("term-number-"+LeadingZeros(key,3)).focus();
	}
	//ripple the number change through to everywhere it occurs in the dp_data array...
	for(var day in dp_data) {
		for(var seg in dp_data[day]) {
			if(!dp_data[day][seg]['dp_colour_id']) {dp_data[day][seg]['dp_colour_id']=WhichNum(dp_data[day][seg]['dp_number_id']);}
			if(dp_data[day][seg]['dp_colour_id']==key) {
				//set the display field: This value gets displayed in the tooltips, so set it to appropriate value, whichever data type is used.
				dp_data[day][seg]['number']=GetDPNumDesc(key,ftype);
			}
		}
	}
}

function LeadingZeros(num,len) {
	num=num.toString();
	while(num.length<len) { num="0"+num; }
	return num;
}

function SetMode(value,nowarn) {
	//Change the page mode between simple and advanced modes.
	var yes=true;
	if(value=='threeday' && !nowarn) {
		yes=confirm("Warning: Switching to three-day mode will lose any changes you may have made for the individual weekdays. Are you sure you wish to switch?")
	}
	if(!yes) {
		document.getElementById("pagemode").value=defmode;
		return false;
	}

	defmode=value;
	document.getElementById("one_weekday").className=(value=='threeday')?"dp_show":"dp_hide";
	document.getElementById("all_weekdays").className=(value=='sevenday')?"dp_show":"dp_hide";
	if(value=='threeday') {
		DayDiv('wk',1);		//need to make sure the visible div is kept in sync with dp_data
	}
	if(value=='sevenday') {
		//if 7 day, then update all the week data to the same as monday, and refresh all the sliders...
		DayDiv('mo',1);
		CopyDPDay(1,2);
		DayDiv('tu',2);
		CopyDPDay(1,3);
		DayDiv('we',3);
		CopyDPDay(1,4);
		DayDiv('th',4);
		CopyDPDay(1,5);
		DayDiv('fr',5);
	}
}

function CopyDPDay(fromdaynum,todaynum) {
	//copy all vars in one part of the array to another
	//(note this can't be done simply by array[1]=array[2] because that would copy by ref, and we want by val)
	dp_data[todaynum]=new Array;
	for(var seg in dp_data[fromdaynum]) {
 		dp_data[todaynum][seg]=new Array;
		for(var field in dp_data[fromdaynum][seg]) {
			dp_data[todaynum][seg][field]=dp_data[fromdaynum][seg][field];
		}
	}
}

function CompareArrays(fromarray,toarray) {
	//compare all vars in one part of the array with another. Return true if identical; false if not.
	for(var fld in fromarray) {
		if(fld!='id' && fld!='dow') {
			var cmpa=fromarray[fld]; var cmpb=toarray[fld]
			if(isObject(cmpa) && isObject(cmpb)) {if(!CompareArrays(cmpa,cmpb)) {return false;}}	//if both a and b are arrays, then compare them.
			else if(isObject(cmpa) || isObject(cmpb)) {return false;}		//but if not, and one of them is, then they're obviously not identical, so the function fails.
			else if(cmpa!=cmpb) {return false;}					//both are simple variables, so compare them and fail if not same.
		}
	}
	for(var fld in toarray) {
		if(fld!='id' && fld!='dow') {
			var cmpa=fromarray[fld]; var cmpb=toarray[fld]
			if(isObject(cmpa) && isObject(cmpb)) {if(!CompareArrays(cmpa,cmpb)) {return false;};}	//if both a and b are arrays, then compare them.
			else if(isObject(cmpa) || isObject(cmpb)) {return false;}		//but if not, and one of them is, then they're obviously not identical, so the function fails.
			else if(cmpa!=cmpb) {return false;}					//both are simple variables, so compare them and fail if not same.
		}
	}
	return true;	//passed all checks, so return true.
}

function isObject(a) {
	return (a && typeof a == 'object');
}

function dp_savechanges() {
	//Uses XMLHTTPRequest to save the changes.
	var saveobj=new Object;

	saveobj["dp_mode"]=defmode; //'threeday';
	saveobj["dp_name"]=document.getElementById("dp_name").value;
	saveobj["dp_id"]=G_dpid;
	saveobj["func"]=(G_dpid>0?"edit":"create");	//delete is called from a separate button.

	for(var dow=1; dow<=7; dow++) {
		var savedow=(defmode=='threeday' && dow>1 && dow<6)?1:dow;
		var dayarr=dp_data[savedow];
		var seg=0;
		for(var segarr in dayarr) {
			seg++;
			var cid=dayarr[seg]['dp_colour_id'];	//check whether the block points to a deleted number, and if so, carry out our threat of setting that block to inactive.
			if(!cid) {cid=0; dayarr[seg]['dp_colour_id']=0;}
			if(!dp_numlist[cid]['number'] && dp_numlist[cid]['rpid']==0 && dp_numlist[cid]['mbid']==0) {dayarr[seg]['dp_colour_id']=0; dp_data[savedow][seg]['dp_colour_id']=0;}

			saveobj["dpd|"+dow+"|"+seg+"|start_time"]=dayarr[seg]['start_time'];
			saveobj["dpd|"+dow+"|"+seg+"|end_time"]=dayarr[seg]['end_time'];
			saveobj["dpd|"+dow+"|"+seg+"|dp_colour_id"]=dayarr[seg]['dp_colour_id'].toString();	//toString req for Konqeror when value=0; otherwise it ignores the field, resulting in save error.
		}
	}
	for(var colour_id in dp_numlist) {
		if(colour_id<=1 || dp_numlist[colour_id]['number'] || dp_numlist[colour_id]['rpid']>0 || dp_numlist[colour_id]['mbid']>0) {
			saveobj["nls|"+colour_id]=dp_numlist[colour_id]['id']+"|"+dp_numlist[colour_id]['number']+"|"+dp_numlist[colour_id]['rpid']+"|"+dp_numlist[colour_id]['mbid'];
		}
	}
	apilite_post('dp_includes/dp_save.php',saveobj, 'SaveOK', saveobj , 'SaveFail', saveobj, true);
}

function SaveOK(responsestring,args) {
	var info=responsestring.split("|");
	document.getElementById("saveinfo").innerHTML=info[1];

	if(args.func=='create') {
		if(G_CurrRec) {document.getElementById("dtr_"+G_CurrRec).style.backgroundColor=bg_def;}	//remove highlight from currently active record (there shouldn't be one anyway, but just in case)
		G_dpid=info[0];		//get the returned DP ID.
		G_CurrRec=info[0];	//get the returned DP ID.
		G_Table[G_CurrRec]=new Array;
		G_Table[G_CurrRec]={id:G_CurrRec,inuse:false, name:document.getElementById('dp_name').value, inuse_yn:'No'};
		G_Table[G_CurrRec].name=document.getElementById('dp_name').value;

		AddLineToList(G_Table[G_CurrRec]);
		document.getElementById("dtr_"+G_CurrRec).style.backgroundColor=bg_selover;	//highlight the newly created record in the list.
	} else {
		G_dpid=args.dp_id;
		G_CurrRec=args.dp_id;
		G_Table[G_CurrRec].name=document.getElementById('dp_name').value;
		//any other fields? not yet.
		RefreshRow(G_Table[G_CurrRec]);
	}
	alert(info[1]);	//display the message in an alert box as well.
}

function SaveFail(responsestring,args) {
	var info=responsestring.split("|");
	if(info[1]) {info[0]=info[1];}
	document.getElementById("saveinfo").innerHTML="<span class='interfaceMedText'>"+info[0]+"</span>";
	alert(info[0]);	//display the message in an alert box as well.
}

//Load DP data with the specified ID.
//Called when the user clicks on one of the entries in the DP list.
function LoadDPData(dpid) {
	DPVisible(false);
	document.body.style.cursor="wait";
	document.getElementById("saveinfo").innerHTML="Please wait... loading day parting data...";
	var apicall="getonedayparting.php?dpid="+dpid;
	apilite_call(apicall, 'LoadOK', "", 'LoadFail', "");
}

function LoadOK(responsestring,args) {
	var res=responsestring.split("\n");
	//res[0] is number of results: this should always be 1 if we got this far.
	if(res[0]!=1) {
		document.getElementById("saveinfo").innerHTML="Error: Expected 1 day parting result; got "+res[0]+".";
		document.body.style.cursor="";
		alert("Error: Expected 1 day parting result; got "+res[0]+".");	//display the message in an alert box as well.
		return;
	}
	//res[1] is the main DP record, fields pipe delimited. (dpid|name|createdate|inuse)
	var maindp=res[1].split("|");
	G_dpid=maindp[0];
	document.getElementById("dp_name").value=maindp[1];

	//res[2] is the number list: numbers are %% delimited; fields within numbers are pipe delimited.
	var nlist=res[2].split("%%");
	dp_numlist=new Array;
	for(var nl in nlist) {	//(destID|seq|routetype|number|routeplanID)
		var nldata=nlist[nl].split("|");
		if(nldata[0]) {
			dp_numlist[nldata[1]]={id:nldata[0],dp_id:G_dpid,number:nldata[3],rpid:nldata[4],mbid:nldata[5]};
		}
	}

	//res[3] is dp days/segs: segs are && delimited; fields within them are pipe delimited.
	var dlist=res[3].split("&&");
	var prevday=0; var prevseg=0;
	dp_data=new Array;
	for(var count=1; count<=7; count++) { dp_data[count]=new Array; }
	for(var dl in dlist) {	//(daynum|seg|dpitemID|starttime|dpdestID|destseg|startseg)
		var dldata=dlist[dl].split("|");
		if(dldata[0]) {
			//Yikes this code is scary to look at! All we're actually doing here is populating the dp_data array from the delimited data we received from the API...
			dp_data[dldata[0]][dldata[1]]={id:dldata[2],dp_id:G_dpid,dow:dldata[0],time_seg:dldata[1],start_time:dldata[3],end_time:'00:00',max_time:'00:00',dp_number_id:dldata[4],dp_colour_id:dldata[5],number:dp_numlist[dldata[5]]['number'],start_seg:dldata[6],end_seg:96};
			dp_data[dldata[0]][dldata[1]]['number']=GetDPNumDesc(dldata[5]);
// 			if(dp_numlist[dldata[5]]['rpid']>0 && G_Routeplans[dp_numlist[dldata[5]]['rpid']]) {
// 				dp_data[dldata[0]][dldata[1]]['number']=G_Routeplans[dp_numlist[dldata[5]]['rpid']]['name'];
// 			}
			if(prevday==dldata[0]) {dp_data[prevday][prevseg]['end_time']=dp_data[dldata[0]][dldata[1]]['start_time']; dp_data[prevday][prevseg]['end_seg']=dp_data[dldata[0]][dldata[1]]['start_seg'];}
			prevday=dldata[0]; prevseg=dldata[1];
		}
	}
	var dm=true;	//check if all five weekdays are the same....
	for(var ct=2; ct<=5; ct++) {
		if(dm) {
			dm=CompareArrays(dp_data[1],dp_data[ct]);
		}
	}
	defmode=(dm?"threeday":"sevenday");
	document.getElementById('pagemode').value=defmode; //'threeday';

	InitialiseDPDivs();
	document.getElementById("saveinfo").innerHTML="Day parting data loaded successfully.";
	DPVisible(true);
	document.body.style.cursor="";
}

function GetDPNumType(key) {
	if(dp_numlist[key]['rpid']>0) {return 'routeplan';}
	if(dp_numlist[key]['mbid']>0) {return 'voicemail';}
	return 'number';
}

function GetDPNumDesc(key,ftype) {
	if(!ftype) {ftype=GetDPNumType(key);}
	switch(ftype) {
		case 'number'    : return dp_numlist[key]['number']; break;
		case 'routeplan' : return G_Routeplans[dp_numlist[key]['rpid']]['name']; break;
		case 'voicemail' : return G_Mailboxes[dp_numlist[key]['mbid']]['name']; break;
	}
}

function LoadFail(responsestring,args) {
	var info=responsestring.split("|");
	if(info[1]) {info[0]=info[1];}
	document.getElementById("saveinfo").innerHTML="<span class='interfaceMedText'>"+info[0]+"</span>";
	document.body.style.cursor="";
	alert(info[0]);
}

//ResetToDefault: Blanks the current day parting data, puts a blank default data set in its place, and redraws the page.
//This is used by the "Add new" option.
function ResetToDefault() {
	G_dpid=-1;
	defmode='threeday';
	document.getElementById('pagemode').value='threeday';

	dp_numlist=new Array;
	dp_numlist[0]={id:0,dp_id:G_dpid,number:'',rpid:0,mbid:0};

	dp_data=new Array;
	for(var count=1; count<=5; count++) {		//count through the 5 days of the week (mon to fri)
		dp_data[count]=new Array;
		dp_data[count][1]={id:1,dp_id:G_dpid,dow:count,time_seg:1,start_time:'00:00',end_time:'09:00',max_time:'13:00',dp_number_id:0,dp_colour_id:0,number:'',start_seg:0,end_seg:36};
		dp_data[count][2]={id:1,dp_id:G_dpid,dow:count,time_seg:2,start_time:'09:00',end_time:'13:00',max_time:'17:45',dp_number_id:0,dp_colour_id:0,number:'',start_seg:36,end_seg:52};
		dp_data[count][3]={id:1,dp_id:G_dpid,dow:count,time_seg:3,start_time:'13:00',end_time:'14:00',max_time:'21:00',dp_number_id:0,dp_colour_id:0,number:'',start_seg:52,end_seg:56};
		dp_data[count][4]={id:1,dp_id:G_dpid,dow:count,time_seg:4,start_time:'14:00',end_time:'18:00',max_time:'00:00',dp_number_id:0,dp_colour_id:0,number:'',start_seg:56,end_seg:72};
		dp_data[count][5]={id:1,dp_id:G_dpid,dow:count,time_seg:5,start_time:'18:00',end_time:'00:00',max_time:'00:00',dp_number_id:0,dp_colour_id:0,number:'',start_seg:72,end_seg:96};
	}
	for(var count=6; count<=7; count++) {		//count through the 2 days of the weekend (sat & sun)
		dp_data[count]=new Array;
		dp_data[count][1]={id:1,dp_id:G_dpid,dow:count,time_seg:1,start_time:'00:00',end_time:'00:00',max_time:'00:00',dp_number_id:0,dp_colour_id:0,number:'',start_seg:0,end_seg:96};
	}

	InitialiseDPDivs();
}

function DPVisible(vis) {
	document.getElementById('maindaypartingtable').style.visibility=(vis?"visible":"hidden");
	document.getElementById('maindaypartingtable').style.display=(vis?"block":"none");
}
//IsValidPhonenum
//Determines whether the string is a valid phone number.
//Parses for both UK and International number formats. It's fairly forgiving for the exact format, especially for international numbers
//as there's various different formats people use, but there are a few rules we can be sure of.
//AllowIntl: if true, then function allows international numbers (in "+44 1628...." format)
//AllowPremium: if true, then function allows premium rate UK numbers (eg 0871..., 09..., 070...)
//Example usage: if(IsValidPhonenum('01234 567890')) { document.write "It's valid.";}
function IsValidPhonenum(testnum,allowIntl,allowPremium) {
	var count=0;
	var CurrChar='';
	var bra=0;
	var ket=0;
	var international=false;
	var firstdigit='';
	var seconddigit='';
	var thirddigit='';
	var AllChars="+-() .0123456789";
	var Digits="0123456789";

	var Good2ndDigits="1278";
	var Bad3rdDigits=new Array;
	Bad3rdDigits[1]="";		//allow all 01... and 02... numbers
	Bad3rdDigits[2]="";
	Bad3rdDigits[7]="0";		//prevent 070... but allow all other 07... numbers
	Bad3rdDigits[8]="7";		//prevent 087... but allow all other 08... numbers

	if(testnum.length<10 || testnum.length>25) { return(false); }	//Too long or too short - I'm expecting all valid numbers to be between 10 and 25 characters (this should allow even for long international numbers, unless they pad it with loads of spaces)

	for (count=0;count<testnum.length;count++) {
		CurrChar=testnum.charAt(count);
		if(AllChars.indexOf(CurrChar)==-1) { return(false); }	//All characters in the string must be in the valid characters array.
		if(count==0 && CurrChar=="+") { international=true; }
		if(count>0  && CurrChar=="+")      { return(false); }	//Plus sign only allowed in first character (for international codes)
		if(CurrChar=="(") bra++;		//count the number of open-brackets.
		if(CurrChar==")") ket++;		//count the number of close-brackets.

		if(international && !allowIntl) { return false; }

		if(thirddigit=='' && seconddigit!='' && Digits.indexOf(CurrChar)>-1) {
			thirddigit=CurrChar;
			if(!allowPremium && !international && Bad3rdDigits[seconddigit].indexOf(thirddigit)!=-1) {
				return(false);		//UK 07 and 08 numbers need additional check to prevent premium-rate numbers being entered
			}
		}
		if(seconddigit=='' && firstdigit!='' && Digits.indexOf(CurrChar)>-1) {
			seconddigit=CurrChar;
			if(!international && Good2ndDigits.indexOf(seconddigit)==-1) {
				return(false);		//We're only allowing UK numbers that start with 01, 02, 07 or 08.
			}
		}
		if(firstdigit=='' && Digits.indexOf(CurrChar)>-1) {
			firstdigit=CurrChar;
			if(international ^ firstdigit!="0") {
				return(false);		//UK numbers must start with zero for the area code; international numbers can start with anything except zero. (that ^ symbol is Javascript's xor operator)
			}
		}
	}
	if(bra!=ket) { return(false); }			//open+close bracket counts don't match?

	return(true);
}

function QueryStringToArray(querystring) {
	var paramArray=new Array;
	var urlgetstr='';
	if(querystring.indexOf("?")>=0) {
		urlgetstr=querystring.substr(querystring.indexOf("?")+1);
	} else {
		urlgetstr=querystring;
	}
	var params=urlgetstr.split("&");
	for(var count=0;count<params.length;count++) {
		var sp=params[count].split("=");
		paramArray[sp[0]]=sp[1];
	}
	return paramArray;
}

function InitialiseDPDivs() {
	// Populate the various divs with the data from dp_data...
	DayDiv('wk',1);
	DayDiv('mo',1);
	DayDiv('tu',2);
	DayDiv('we',3);
	DayDiv('th',4);
	DayDiv('fr',5);
	DayDiv('sa',6);
	DayDiv('su',7);

	// Display them in the correct default mode.
	document.getElementById("one_weekday").className=(defmode=='threeday')?"dp_show":"dp_hide";
	document.getElementById("all_weekdays").className=(defmode=='sevenday')?"dp_show":"dp_hide";
	document.getElementById("pagemode").value=defmode;

	PutNumbers();
}


