///////////////////////////////////////
// maxDynamic
//	code used in the fully dynamic version of the site
// load maxBase,maxCustom,maxPopups, maxDynamic and maxDegrees*
// to render pages, popups and interpretations on the fly.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

function interpSetup() {

	MAX.NAV= new ZodiacNav()
	MAX.NAV.changed= (function() {document.location=document.location})

	switch (MAX.SITE.where) {
//	case 'about':
//		MAX.SITE.SwapMenu('menu','about')
//		return
	case 'index':
		MAX.BROWSER.createCookie('lastPage',MAX.SITE.where+'.htm?')
		break
		}
	addLoadEvent(interp)
	}

///////////////////////////////////////
// process the pages

function interp() {
	//interpSetup() 
	if (typeof(MAX.NAV.p)=='undefined') {MAX.NAV.setSym('ari01')}
	var ddeg=MAX.NAV.p.ddeg
	//
	function setup(area,view,menu,which,step) {
//		if (which='degree') {NAV.extra=''} 	else 
		{MAX.NAV.extra=MAX.SITE.renderSubMenu(menu,view)}
//		{MAX.NAV.extra=MAX.SITE.renderSubMenu(menu,which)}
		MAX.SITE.SwapMenu(area,view,MAX.NAV.extra)	
		if (typeof(step)=='undefined') {step=1}
		MAX.NAV.linkTo=which+'/?'
		MAX.NAV.pnext= MAX.NAV.prevNext(step,'') //#nav')
		}
	//
		function formatPage(lt1,lt2,b1,b2){
			b1=!b1
			b2=!b2
			//out=INTERP.formatPage(out,'degree/?','degree/?','',)
//			BROWSER.getElementById('xSigns').innerHTML= 
			MAX.set('xDegrees', '<table><tr><td>' +MAX.NAV.getSignLinks(lt1)
				+'</td><td>'+MAX.SITE.getProportionLinks()
				+'<span id=XSize></span>' 
				+'</td>' 
				+'</tr><tr><td colspan=2>'
				+MAX.NAV.getDegreeLinks(lt2)
				+'</td></tr></table>' )
			//alert(b1+'-'+b2)
//			if (b1){BROWSER.getElementById('xProportions').innerHTML= NAV.getProportionLinks()}
//			if (b2){BROWSER.getElementById('xSize').innerHTML= 'Choose Sizes<br>1 2 3 4 99'}
			//if (b2){BROWSER.getElementById('XSize').innerHTML= 'Size:<br>1 2 3 4 99'}
		
			//var x=BROWSER.getElementById('xInterp')
			//if (x!=null){alert(x); x.innerHTML= NAV.getDegreeLinks(INTERP.interp(ddeg))}
			}

	var out=''
	var txts='<table width=72%><tr><td>\n', txte='</td></tr></table>\n'
	switch (MAX.SITE.where) {

	/////////////////////////////////
//	case 'index':
//		SITE.SwapMenu('menu','index')
//		break;
	case 'browse':
		MAX.NAV.href=true
		setup('menu','browse','Browse','browse')
		formatPage('aspect/?','aspects/?')
		MAX.LB= new Lightbox('thimage','iimage','extra')
		MAX.LB._deg(MAX.NAV.p.deg)
		MAX.NAV.changed= (function() {MAX.LB._deg(MAX.NAV.iDegree)})
		break;

	/////////////////////////////////
	case 'gallery':
		MAX.NAV.houses= {}
		setup('menu','degrees-gallery','Browse','gallery',1)
		var a= MAX.NAV.sym;	if (!a) {a=''} else {a='?'+a}
		out=MAX.INTERP.delineateGallery()+'<p>'
			+txts
			+'(<b><a href="/gallery/cycle/'+a+'">ALTERNATE VIEW: 4x3</a></b>)<p>'
			+'Presented as per Ax\'s electrical analysis, you\'re looking at 6 dipoles, magnets if you will. These have the male-end on top, the female on the bottom.\n'
			+'You will notice how in this arrangement the impulse or idea from the yin sign invariably sublimates into the yang half, and, transformed, continues there..<p>\n'
			+'On a subtle level this phenomena adds proof to the idea that something fascinating is going on within both, the degrees, and this arrangement.<p>\n'
			+'In the center note how the cluster of fixed signs tends to hold one set of ideas - while the wings to the left and right develop other themes which line up\n'
			+'surprisingly well. Consider the fixed signs to complete themselves horizontally as well. Their position in the center of the diagram is/was dictated by that.<p>\n'
			+'A summary guide to the elements is posted <a href="http://sonic.net/~ax/articles/zodiax/Zodiax.Compass.pdf">here</a>. This one page reference will help\n'
			+'you to put the right words and concepts to the interpretation of the four alchemical  elements.<p>\n'
			+txte
		formatPage('sign/?','gallery/?')
		break;
	case 'sign':
		setup('menu','sign-gallery','Browse','sign',30)
		out=MAX.INTERP.delineateSign(30)
		formatPage('sign/?','degree/?')
		break;

	/////////////////////////////////
	case 'degree':
		if (MAX.NAV.sym.indexOf(',')>=0) {var a='list-'} else {var a=''}
		setup('menu',a+'view','Browse','degree',1)
		out='<p>'+MAX.NAV.pnext+'<br>\n'
			+'<a href="degree/mirror/?'+MAX.NAV.sym+'"><b>Mirror</b></a><br>\n'
			+MAX.INTERP.delineateDegree(ddeg,'+1')
			+MAX.NAV.pnext+'<p>'
		if (false) {	out+=''
			+'By reflecting the degrees we allow transcendental considerations<br>to be expressed by the series imagery rather than words:'
			+'<table cellpadding=4 class=ttb><tr><th>Interior Mirrors</td><th>Exterior Mirrors</td></tr><tr><td valign=top>'
			+MAX.INTERP.delineateTinyMirrors(ddeg,'',true,'')//' bgcolor=whitesmoke')
			+'</td><td valign=top>'
			+MAX.INTERP.delineateTinyMirrors(ddeg,'',false,'')// bgcolor='+SITE.degreeColor(ddeg))
			+'</td></tr></table>'
			+MAX.NAV.pnext+'<p>'
			}
		formatPage('degree/?','degree/?')
		break;
	case 'mirror':
		if (MAX.NAV.sym.indexOf(',')>=0) {var a='list-'} else {var a=''}
		setup('menu',a+'view','Browse','degree/mirror',1)
		//out=MAX.INTERP.delineateMirrors(ddeg,'+1')
		if (true) {	out+=''
			+'<p>'
			+'By reflecting the degrees we allow transcendental considerations<br>to be expressed by the series imagery rather than words:'
			+'<p>'
			+MAX.NAV.pnext+'<br>'
			+'<a href="degree/?'+MAX.NAV.sym+'"><b>Un-Mirror</b></a><p>\n'
			+'<table cellpadding=4 class=ttb><tr><th>Interior Mirrors</td><th>Exterior Mirrors</td></tr><tr><td valign=top>'
			+MAX.INTERP.delineateTinyMirrors(ddeg,'',true,'')//' bgcolor=whitesmoke')
			+'</td><td valign=top>'
			+MAX.INTERP.delineateTinyMirrors(ddeg,'',false,'')// bgcolor='+SITE.degreeColor(ddeg))
			+'</td></tr></table>'
			+MAX.NAV.pnext+'<p>'
			}
		formatPage('degree/mirror/?','degree/mirror/?')
		MAX.NAV.extra=''
		break;

	/////////////////////////////////
	case 'cycle':
		setup('menu','cycles-gallery','Browse','gallery/cycle',1)
		out=MAX.INTERP.delineateCycles(3,4)
		formatPage('gallery/cycle/?','gallery/cycle/?')
		break;
	case 'decan':
		setup('menu','decans-gallery','Browse','aspect/decan',3*6*10)
		out=MAX.INTERP.delineateDecans(3,6)
		formatPage('aspect/decan/?','aspect/decan/?')
		break;
	case 'trine':
		setup('menu','elements-gallery','Browse','aspect/trine',6)
		out=MAX.INTERP.delineateDecans(3,6,'aspect/trine/?',120,6)+'<p>\n'
			+txts
			+'This is a good page to confirm the accuracy of degrees in your chart.\n'
			+'If you\'re undecided between a few degrees, line them up on the left side of this page'
			+'and study the resonances along the trine.<br>'
			+'Through the elemental trines you get a views into the potential of each participating degree\n'
			+'and by having lived your life, you can usually tell the right originating degree by its resonances.<p>\n'
			+'Also remember that the Sun and Moon are roughtly 32\' and 31\'s arc-seconds wide respectively.\n'
			+'This means that unless they are in the middle half of a degree, they may be carrying the resonance and\n'
			+'ideas of the prior or next degrees. Thus for the lights, sun and moon, look at how you may be blending the\n'
			+'two degrees in your life. (e.g. 1/3 this, 2/3 that... day side, night side.. how far does your sun extend left/right?)'
			+'them you can usually identify the exact degree from \'close choices\'. '
			+txte
		formatPage('aspect/trine/?','aspect/trine/?')
		break;
	case 'square':
		setup('menu','quarters-gallery','Browse','aspect/square',3)
		out=MAX.INTERP.delineateDecans(3,4,'aspect/square/?',90,3)
		formatPage('aspect/square/?','aspect/square/?')
		break;
	case 'quintile':
		setup('menu','quintiles-gallery','Browse','aspect/quintile',3)
		out=MAX.INTERP.delineateDecans(3,5,'aspect/quintile/?',72,3)
		formatPage('aspect/quintile/?','aspect/quintile/?')
		break;

	/////////////////////////////////
	case 'calendar':
		setup('menu','calendar-gallery','Browse','calendar',28)
		out=MAX.INTERP.delineateDecans(6,7,'calendar/?',1,28,80)
		formatPage('calendar/?','calendar/?')
		break;
	case 'all':
		setup('menu','all-gallery','Browse','all',28)
		out=MAX.INTERP.delineateDecans(40,9,'ax/all.html?',1,28,80,false)
		formatPage('ax/all.html?','ax/all.html?')
		break;

	/////////////////////////////////
/*	case 'chart':
		alert('chart:\n'+MAX.NAV.extra)
		//MAX.NAV.extra=MAX.SITE.renderSubMenu('Browse','')
		MAX.SITE.SwapMenu('menu',MAX.SITE.where,MAX.NAV.extra)
		formatPage('sign/?','gallery/?',true,true)
		break; */
	default:
		if (!MAX.NAV.extra) {
			MAX.NAV.extra=MAX.SITE.renderSubMenu('Browse','')
			}
		MAX.SITE.SwapMenu('menu',MAX.SITE.where,MAX.NAV.extra)
		formatPage('sign/?','gallery/?',true,true)
		break;
	/////////////////////////////////
		}
	//
	switch (MAX.SITE.where) {
	case 'degree':// border
		out='<table><tr><td valign=top id=xLeft></td><td>&nbsp;</td><td valign=top width=100%><center>'
		+out+'</center></td><td>&nbsp;</td><td valign=top id=xRight></td></tr></table>'
		break;
		}	
	//
	var im= MAX.BROWSER.getElementById('reinterp')
	if (im!=null) {im.innerHTML=out} else {if (out!='') {document.write(out)}}
	//
	switch (MAX.SITE.where) {
	case 'degree':

//		var x=BROWSER.getElementById('xLeft')
//		if (x!=null){x.innerHTML= INTERP.interpleft(ddeg)}

//		var x=BROWSER.getElementById('xRight')
//		if (x!=null){x.innerHTML= INTERP.delineateTinyMirrors(ddeg,'')
			//INTERP.interp(ddeg)
//			}
	
		var im= MAX.BROWSER.getElementById('oneimg')
//		im.height= BROWSER.ClientHeight()-300 //240// im.y
		//break //no, stay
	case 'browse':
	case 'cycle':
	case 'decan':
	case 'elements':
	case 'gallery':
	case 'mirror':
	case 'quarters':
	case 'quintiles':
	case 'sign':
		MAX.BROWSER.setLastPage(MAX.SITE.where+'/?'+MAX.NAV.p.sym)
	default:
		}	
	//
	finishSite()
	}

///////////////////////////////////////

///////////////////////////////////////

///////////////////////////////////////

///////////////////////////////////////

/////////////////////////////////////// 
// the NAV Object

function ZodiacNav() {
	//
	this.iwords=1		//symbol-word toggle for degree display
	this.aDegree=1
	this.aSign=''
	this.iSign=0
	this.extra=''
	//
	this.href=true
	this.popup=true
	//
	this.linkTo='degree/?'
	this.queryObj= MAX.BROWSER.parseQueryString('sym=ari01')
	this.setSym(this.queryObj.sym)
	}

ZodiacNav.prototype.toString = function() 
	{return 'aDeg='+this.aDegree+', aSign='+this.aSign+', iSign='+this.iSign}

ZodiacNav.prototype.changed= function() {} //update the gui.. replace me!

ZodiacNav.prototype.popupJS= function(degree,onMouseOver) {
	if (!this.popup) {return''}
	if (!onMouseOver) {onMouseOver='i('+degree+')'}	
	return ' onMouseOver="'+onMouseOver+'"' +' onMouseOut="o()" '
	}

///////////////////////////////////////

ZodiacNav.prototype.setSym= function(sym) {
	if (sym) {
		this.sym=sym
		this.p= new Planet('point',sym) 
		this.ToDeg(this.p.ddeg)
		}
	}

ZodiacNav.prototype.setDeg= function(deg) {
	if (deg) {
		this.p= new Planet('point',deg) 
		this.sym=this.p.sym
		this.ToDeg(this.p.ddeg)
		}
	}

ZodiacNav.prototype.imgTo= function(deg,tolink) {
	if (typeof(deg)=='number')	{deg=MAX.SITE.asym(deg)}
	if (typeof(tolink)=='string' && tolink.length>0)
		{return tolink+deg} 
	else {return this.linkTo+deg}
	}

/////////////////////////////////////// GENERIC SIGN TEXT LOOKUPS++

ZodiacNav.prototype.anExtra= function() {
	if (this.extra!='') {return '<hr>'+this.extra}
	return ''}

/////////////////////////////////////// 
// navigating to signs and degrees

ZodiacNav.prototype.ToSign= function(tosign) {	// switch to this degree in that sign
	for (var i=0; i<12; i++ ) { 
		if (MAX.SITE.signs[i]==tosign)
			{this.ToDeg( i*30+this.aDegree ); break } }
	}

ZodiacNav.prototype.ToDeg= function(todeg) {	// switch to degree by number
	this.setDeg(todeg);
	this.changed();
	}

ZodiacNav.prototype.setDeg= function(Degree) {		// update internal, degree related properties
	this.iDegree= wrapdeg(Degree);
	this.iSign= MAX.Div(this.iDegree-1,30);
	this.aSign= MAX.SITE.signs[this.iSign];
	this.aDegree= this.iDegree - 30 * this.iSign;
	}

/////////////////////////////////////// 
// clickable grid of signs

ZodiacNav.prototype.linkOneSign= function(sign,fc,sp,skipsame,width) {
	var a='';
	width=(typeof(width)=='number')?width:1000
	if ( this.iwords>0 ) { a= sign.substr(0,width) }
		else { a= '<img src="sym\\si'+sign+'.gif">' };
	if (skipsame & sign==this.aSign) 
		{return a.toUpperCase()+sp+'\n'}
	else 
		{	
		if (!this.href) {
			return '<a title="Switch to '+sign+'" href="javascript:MAX.NAV.ToSign(\''+sign+'\')">'+a+'</a>'+sp+'\n'}		
		else {
			var deg=0
			for (var i=0; i<12; i++ ) { //inline ToSign:
				if (MAX.SITE.signs[i].substr(0,3)==sign.substr(0,3)) { deg= i*30+this.aDegree ; break } }
			return this.linkOneDegree(deg,a,'',false)
			}			
		 }
	}

ZodiacNav.prototype.linkSigns= function(width) {
	var  out='<table cellpadding=0 cellspacing=3>'
	for (var r=0; r<4; r++ ) {
		out+'<tr>'
		for (var c=0; c<3; c++ ) {
			out+='<td bgcolor="'+MAX.SITE.signColors[r*3+c]+'"><font size=-1><b>'
			out += this.linkOneSign(MAX.SITE.signs[r*3+c],'','',false,width)
			out += '</b></font></td>'
			}
		out+='</tr>'
		}
	return out +'</table>'
	}

/////////////////////////////////////// 
// clickable grid of degrees

ZodiacNav.prototype.linkOneDegree= function(degree,caption,title,skipsame) {
	//
	function addQryParam(base,param){
		if (base.indexOf('?')==base.length-1) {return base+param}
		if (base.indexOf('?')>-1) {return base}
		return base+'?'+param}
	//
	var b= this.popup
	degree=wrapdeg(degree);
	if (typeof(title)=='undefined') { title='' }
	else { 
		if (title.substr(0,1) == '-')	{ 
			title= title.substr(1,1000) 
			b=false
			}
		title=' title="'+title+'"' 
		};

	if (b) {
		title +=  this.popupJS(degree)
		}

			skipsame=false //we're not comparing apples to oranges yet

	if (skipsame & degree== this.aDegree) 
		{ return '<b>'+degree+'</b>\n'; }	
	else 
		if (!this.href) {
			return '<a'+title+' href="javascript:MAX.NAV.ToDeg('+degree+')">'+caption+'</a>'	}		
		else {
			return '<a'+title+' href="'+addQryParam(this.linkTo,MAX.SITE.asym(degree))+'">'+caption+'</a>'	}
	}

ZodiacNav.prototype.linkDegreeRange= function(low,high,div) {
	if (!div) {div='<br>'}
	var out=''
	for (var i=low; i<=high; i++ ) { out += this.linkOneDegree(30*this.iSign+i,i,'',true) +div }
	return out
	}

ZodiacNav.prototype.linkDegrees= function(p) {
	var td='<tr><td width=3% class=1 align=right valign=top><font size=-1>',etd='</font></td></tr>'
	var out='<table width=1% cellpadding=0 cellspacing=0>'
	out+= td+'<a href="sign/?'+p.sym+'"><font size=+1>Degree:</font></a>&nbsp;'+this.linkDegreeRange(1,10,'&nbsp;')+etd
	out+= td+this.linkDegreeRange(11,20,'&nbsp;')+etd
	out+= td+this.linkDegreeRange(21,30,'&nbsp;')+etd
	return out +'</table>'
	};


///////////////////////////////////////

ZodiacNav.prototype.oneDegree= function(degree,caption,title,skipsame,target,onMouseOver) {
//	return MAX.NAV.linkOneDegree(degree,caption,title,skipsame)
	target=(typeof(target)=='undefined')?'':target
	var b=this.popup

	function addParam(qs,param) {
		var n=qs.indexOf('?')
		if (n>-1) {
			if (n<qs.length-1 ) {return qs}
			else {return qs+param}
			}
		else {return qs+'?'+param}
		}

	if (typeof(degree)=='string') {
		var p = new Planet('point',degree)
		degree = p.ddeg
		}

	if (typeof(degree)=='string') {degree='\''+degree+'\''} else {degree=wrapdeg(degree)}

	if (typeof(title)=='undefined') {title=''}
	else { 
		if (title.substr(0,1) == '-')	{ 
			title= title.substr(1,1000) 
			b=false
			}
		title=' title="'+title+'"' 
		}
	if (b) {title +=  this.popupJS(degree,onMouseOver)}

	if (this.href) 
		{return '<a'+title+' href="'+addParam(this.linkTo,MAX.SITE.asym(degree))+target+'">'+caption+'</a>'}
	else 
		{return '<a'+title+' href="javascript:MAX.LB._deg('+degree+')">'+caption+'</a>'}
	}

ZodiacNav.prototype.populateDegrees= function(low,high) {
    var out='';
	for (var i=low; i<=high; i++ ) { out += this.oneDegree(30*iSign+i,i,'',true) + '<br>'; };  //?????????????????????????
	return out;
	}

//iDegree=0

//these link to the LB lightbox object used for the aspects grid
//maybe they should go on that obj
ZodiacNav.prototype._add= function(n,c,t) { return this.oneDegree(MAX.LB.iDegree+n,c,t) }
ZodiacNav.prototype._sub= function(n,c,t) { return this.oneDegree(MAX.LB.iDegree-n,c,t) }
ZodiacNav.prototype._next= function(n,t) { return this._add(n,'<b>+</b>',t) }
ZodiacNav.prototype._prev= function(n,t) { return this._sub(n,'<b>-</b>',t) }


///////////////////////////////////////
// PREV NEXT LINKS

ZodiacNav.prototype.prevNext= function(n,anchor) {
	if (this.sym.indexOf(',')>=0) {	
		return'<a href="degree/?'+MAX.shiftRight(this.sym)+anchor+'"><b>Next</b></a>\n'
			+ '<a href="degree?'+MAX.shiftLeft(this.sym)+anchor+'"><b>Prior</b></a>\n'}
	else {
		return ''
			+this.oneDegree(this.p.deg+n,'<b>Next</b>','-',false,anchor)+'\n' 
			+ this.oneDegree(this.p.deg-n,'<b>Prior</b>','-',false,anchor)+'\n' 
			}
	}

/////////////////////////////////////// 
// menu navigation links

ZodiacNav.prototype.getSignLinks= function(l1) {
	var a=''
	var p= new Planet('point',30*this.iSign+1)
	a+='<center><a href="gallery/?'+p.sym+'"><font size=+1>Sign</font></a></center>\n' //Choose a 
	this.linkTo= l1
	a+= this.linkSigns(3)
	return a
	}

ZodiacNav.prototype.getDegreeLinks= function(l2) {
	var a=''
	var p= new Planet('point',30*this.iSign+1)
	this.linkTo= l2
	a+= this.linkDegrees(p)
	return a
	}

///////////////////////////////////////

///////////////////////////////////////

///////////////////////////////////////

///////////////////////////////////////

/////////////////////////////////////// 
//add THE ZODIAC GRID

// makes a square horoscope like grid of 12 orbiting a center
// pass the text for the 1(2x2) size center when constructing
// pass a function to render the text inside the cells when calling.
// replace or extend funCenter and funCell to alter the looks/style

/*<script>
	var houses= {
		h1:'this site',h2:'it\'s purpose',h3:'some thoughts',
		h4:'philosophical roots',h5:'gold gold gold',h6:'how-to information',
		h7:'audience',h8:'products',h9:'philosophy',
		h10:'goals',h11:'by way of these friends',h12:'what we\'re organizating'}
	var g= new ZodiacGrid('<a href="aspect/"><img border=3 src="img/sabian-cover.gif" alt="Logo"></a>')
	var f= (function(house) {return '&nbsp;<br><br>&nbsp;'+houses['h'+house]+'<br>&nbsp;<br>&nbsp;'} );
	document.write(g.genGrid(f))
</script>*/

function ZodiacGrid(centerText) {
	//the map is read from top left to bottom right as we build the output table
	//thus you get 4 rows of four where by hex numbers you control the argument
	//passed into the on-cell callback.  it's a zodiac-grid after all! you get the sign/house# per this map
	this.setRCM(4,4,'BA98'+'CXX7'+'1XX6'+'2345',false) // classic western chart mapping
	//outer table:
	this.optb= 'cellpadding=0 cellspacing=0 border=5 width=1%'//'width=72% height=72%'
	this.optd= 'align=center valign=top' //middle'
	//inner tables:
	//bc '<table cellpadding=4 width=100% height=100% border=3>'  dc<td align=center valign=middle>'
	this.optbc= 'cellpadding=6 width=100% border=0' // width=200 height=200 
	this.optdc= 'align=center valign=top' //middle'
	this.centerText=centerText
	}

ZodiacGrid.prototype.setRCM= function(rows,cols,map,vert) {
	this.rc=rows
	this.optr= 'rowheight='+MAX.Div(100,this.rc)+'%'
	this.cc=cols
	this.map=map
	this.vert=(!!vert)
	}

ZodiacGrid.prototype.genGrid= function(funCellText) {
	var ndx	=0
	var out	=''
	out+= '<table '+this.optb+'>\n'
	for (var row=0;row<this.rc;row++) {
		out+= '<tr '+this.optr+'>\n'
		for (var col=0;col<this.cc;col++) {
			if (this.map.length>0) {
				var c= this.map.substr(ndx,1)
				var i= parseInt(c,16) }
			else {
				if (this.vert) {
					var r= MAX.Div(ndx,this.cc)
					var c=MAX.Mod(ndx,this.cc)
					i=r+c*this.rc }
				else {i=ndx} }
			if (i>=0)	{
				out+=this.funCell(funCellText(i))+'\n'} 
			else {if (ndx==5) {out+=this.funCenter()+'\n'}}
			ndx++ }
		out+='</tr>\n' }
	return out+'</table>\n'
	}

ZodiacGrid.prototype.funCenter= function() {
	var out='<td rowspan=2 colspan=2 align=center valign=middle>\n' //'+this.optd+'>\n'
	out+='<table border=0>\n<tr><td><span id=gridcenter>\n' //width=100% height=100% 
	out+= this.centerText+'\n'
	out+='</span></td></tr></table>\n'
	out+='</td>\n'
	return out+'</td>\n'
	}

ZodiacGrid.prototype.funCell= function(text) {
	var out='<td width='+MAX.Div(100,this.cc)+'% '+this.optd+'>\n'
	out+='<table '+this.optbc+'>\n<tr><td '+this.optdc+'>\n'
	out+= text+'\n'
	out+='</td></tr></table>\n'
	return out+'</td>\n'
	}

////////////////////////////////////// 

////////////////////////////////////// 

////////////////////////////////////// 

////////////////////////////////////// 

////////////////////////////////////// 
//POINTGRID CALCULATIONS
// add generic degree-difference calcs 
// these get added/used from the main name-space
// in the midpoint grid

function iddelta(i,j) { // integer degree delta
	if (i>j) { i= i-j } else { i= j-i }
	return wrapdeg( Math.ceil( i ) )
	}

function idavg() { // integer degree average (next higher
   var sum = 0;
    for (var i = 0, j = arguments.length; i < j; i++)
		{sum += arguments[i]}
    return wrapdeg( Math.ceil( sum / arguments.length ) )
}

function idmid() { // integer degree midpoint (max to 180
   var sum = 0;
    for (var i = 0, j = arguments.length; i < j; i++)
		{sum += arguments[i]
//		document.write(' '+sum+' ')
		}
    return wrapdeg( Math.ceil( sum / arguments.length ) ,180)
}

function ZodiacCalculations() {
	this['Midpoint']= idmid
	this['Angle']= iddelta
	this['Average']= idavg
	}


////////////////////////////////////// 
// the POINTGRID Object

/*  gridxy() will draw a grid with images linked to points, 
midpoints and angles based on the aPoints[] object. 
mirror - controls if we're filling out 2 sides of the grid
*/

function  PointGrid(points,rfilter,cfilter,mirrr,gmde) {
//	new PointGrid(p,'Sol,Luna,Mercury','',true,'pop');	
	var rfilt= rfilter || ''
	var cfilt= cfilter || ''
	if (typeof(mirrr)=='undefined') {this.mirror=true}
	else {this.mirror= mirrr}
	if (cfilt=='=') {cfilt=rfilt}
	this.same= (rfilt == cfilt)
	this.gmode= gmde || 'pop'
	this.rheader=true
	this.cheader=true
//	this.rheader=false
//	this.cheader=false
	this.inside=true
	this.inside=false
//	document.write(this.gmode+'<br>'+rfilt+'<br>'+cfilt+'<br>'+this.mirror+'-'+this.same+'<hr>')
	//
	this.rpoints= new Object;
	this.cpoints= new Object;
	if (rfilt.length>0) {
		for (var point in points) {
			if (rfilt.indexOf(point)>=0) 
				{this.rpoints[point]=points[point]}
			}}
	else	{this.rpoints= points}
	//
	if (cfilt.length>0) {
		for (var point in points) {
			if (cfilt.indexOf(point)>=0) 
				{this.cpoints[point]=points[point]}
			}}
	else	{this.cpoints= points}
	//
	this.calcs= new ZodiacCalculations();
	}

PointGrid.prototype.toString = function() {
	return this.gridxy()
	}


// functions to make the text and headers

/*
midpoint
average
angle
above-below
self-other
* point ab/be, se/ot
*/

PointGrid.prototype.link= function(n,a) {
	return poponedeg(n,MAX.SITE.asym(n),this.cpoint+'/'+this.rpoint+' '+a)}

PointGrid.prototype.frmt= function(p) {         // FORMAT THE IN-GRID IMAGE
	var n= p.deg, c= p.name, sym= p.sym;
	c+='<br><font size=-1>'+sym+': '+p.ddeg.toFixed(2)+'</font>';
	a= MAX.INTERP.oneWord(n)
	return [poponedeg(n,c,'-'),a,poponedeg(n,'<img src=\''+MAX.SITE.ipath+sym+MAX.SITE.iext+'\' border=0 width=140>','-')];
	}


PointGrid.prototype.rct= function(o) {// row/column text
	switch (o.gmode) {
	case 'pop':
		var r=[]
		for (var calc in o.calcs) {
			var c=o.calcs[calc]
			r[r.length]= o.link( c(o.cp.deg,o.rp.deg), calc )
			}
		return r
	case 'img': 
		var p= new Planet( o.cp.name+'/'+o.rp.name, iddelta(o.cp.ddeg,o.rp.ddeg) ); 
		return o.frmt(p)
	}}
	
PointGrid.prototype.cph= function(o) {// column point header
	switch (o.gmode) {
	case 'pop': return o.cpoint+'<br>'+poponedeg(o.cp.deg,o.cp.sym,o.cpoint+'<br>'+o.cp.ddeg.toFixed(2))
	case 'img': return o.frmt(o.cp)
	}}

PointGrid.prototype.rph= function(o) {// row point header
	switch (o.gmode) {
	case 'pop': return o.rpoint+'<br>'+poponedeg(o.rp.deg,o.rp.sym,o.rpoint+'<br>'+o.rp.ddeg.toFixed(2))
	case 'img': return o.frmt(o.rp)
	}}

PointGrid.prototype.tlh= function(o) {// top left header
	return 'Midpoint<br>Distance'}
//	return ['Midpoint','Distance']}

PointGrid.prototype.mrct= function(o) {// mirrored row/column text
	return o.rct(o)}


// format one or more result cells.
// by returning arrays we can print them into multiple rows/cols.
PointGrid.prototype.tds= function(atd,fun) {
	// the caller must send atd looking like this: atd='<td valign=top class="tlc">'
	// we grab the classname and add the row# for the style.
	var r=fun(this)
	var p=atd.substr(0,atd.length-2)
	if (typeof(r)=='object')	{
		for (var i=0, n=r.length; i<n; i++) {
			r[i]=p+i+'">'+r[i]+'</td>'}
		return r
		}
	else {return p+'0">'+r+'</td>'}
	}

// functions to make/format the different kinds of cells:

PointGrid.prototype.blc= function() {return '<td class="blc"><br></td>'}
PointGrid.prototype.tlc= function() {return this.tds('<td valign=top class="tlc">',this.tlh)}
PointGrid.prototype.cpc= function() {return this.tds('<td valign=top class="cpc">',this.cph )}
PointGrid.prototype.rpc= function() {return this.tds('<td class="rpc">',this.rph)}
PointGrid.prototype.rcc= function() {return this.tds('<td class="rcc">',this.rct)}
PointGrid.prototype.mrcc= function() {return this.tds('<td class="rcc">',this.mrct)}

PointGrid.prototype.outrcc= function() {	
	if (this.cpoint != this.rpoint) {return this.rcc()}
	else 
		{if (this.inside & (this.cp.name == this.rp.name)) {return this.cpc()}
		else {return this.blc()}}
	}


// insert a rowspan adjustment into the first row of columns that are short

function rowspan(a,i,n) {
	if (n>0 && i==0) {
		a= a.substr(0,4)// '<td '
			+'rowspan='+(1+n)
			+ a.substr(3);
		}
	return a
	}

function trs(lin) {
// works for one row, get max and fill in while adjusting row-heights
		if (typeof(lin)!='object') {
		return lin}

	var out=[''], c=0, m=1

	//determine max rows
	for (var i=0, n=lin.length; i<n; i++) {
		var o=lin[i]
		if (typeof(o)=='object') {
			var p= o.length
			if (p>m) {m=p}
			}
		}
	//build up the lines in out[]
	for (var i=0, n=lin.length; i<n; i++) {
		var o=lin[i]
		if (typeof(o)=='object') {
			var p= o.length
			if (p>m) {m=p}
			for (var j=0; j<p; j++) {
				if (typeof(out[j])=='undefined') {out[j]=''}
				out[j]+= rowspan(o[j],j,m-p)
				}
			}
		else {out[0]+= rowspan(o,0,m-1)}
		}

	var a=''
	for (var i=0, n=out.length; i<n; i++) {
		a+= '<tr>'+ out[i] +'</tr>'}
	return	a
	}

PointGrid.prototype.gridxy= function() {
	var out='';
//	out+='<table border>'
	out+='<table>'

	var row=0, cols=0;
	if (this.rheader & !this.mirror) {cols--}
	for (this.cpoint in this.cpoints)
		{cols++}

	if (this.cheader & this.mirror) {
		var lin= []
		if (this.rheader) {lin[lin.length]= this.tlc()}
		for (this.cpoint in this.cpoints)	{
			this.cp=this.cpoints[this.cpoint]
			lin[lin.length]= this.cpc()
			col++
			if (col>=cols)	{break}
			}
		out+= trs(lin)
		}

	for (this.rpoint in this.rpoints) {
		this.rp=this.rpoints[this.rpoint]
		var col=0;
		var lin=[] 

		if (!this.mirror && row==0)
			{if (this.rheader) {lin[lin.length]= this.tlc()}} //this.cheader && 
		else 
			{if (this.rheader)	{
//				if (row==0 && !this.cheader) {lin[lin.length]= this.tlc()} else 
					{lin[lin.length]= this.rpc()}
				}}

		for (this.cpoint in this.cpoints)	{
			this.cp=this.cpoints[this.cpoint]
			if (col>row) {
				if (this.mirror) {lin[lin.length]= this.mrcc()}
				else // {lin[lin.length]= this.blc()}	}
					{if (this.inside & (this.cp.name == this.rp.name)) {lin[lin.length]= this.cpc()}
					else {lin[lin.length]= this.blc()}
					}}
			else 
			if (col==row) {
				if (this.same & this.mirror) 
					{if (this.inside) {lin[lin.length]= this.cpc()}
					else {lin[lin.length]= this.blc()}}
				else 
					if (this.mirror) {lin[lin.length]= this.outrcc()}		
					else {lin[lin.length]= this.cpc()} }
			else {lin[lin.length]= this.outrcc()}
			col++
			if (col>=cols)	{break}
			}
		out+= trs(lin)
		row++
		}
	out+='</table>'
	return out
	}

///////////////////////////////////////

///////////////////////////////////////

///////////////////////////////////////

///////////////////////////////////////

///////////////////////////////////////
//;#
