// Rollover Image

function MM_swapImgRestore() { //v3.0
  var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc;
}
function MM_preloadImages() { //v3.0
  var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array();
    var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++)
    if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}}
}

function MM_findObj(n, d) { //v4.01
  var p,i,x;  if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
    d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
  if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
  for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document);
  if(!x && d.getElementById) x=d.getElementById(n); return x;
}

function MM_swapImage() { //v3.0
  var i,j=0,x,a=MM_swapImage.arguments; document.MM_sr=new Array; for(i=0;i<(a.length-2);i+=3)
   if ((x=MM_findObj(a[i]))!=null){document.MM_sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];}
}

// switches between tabs on the subcategory page (change property: display)
<!--
function MM_changeProp(objId,x,theProp,theValue) { //v9.0
  var obj = null; with (document){ if (getElementById)
  obj = getElementById(objId); }
  if (obj){
    if (theValue == true || theValue == false)
      eval("obj.style."+theProp+"="+theValue);
    else eval("obj.style."+theProp+"='"+theValue+"'");
  }
}
//-->

/*
function MM_changeProp(objName,x,theProp,theValue) { //v6.0
  var obj = MM_findObj(objName);
  if (obj && (theProp.indexOf("style.")==-1 || obj.style)){
    if (theValue == true || theValue == false)
      eval("obj."+theProp+"="+theValue);
    else eval("obj."+theProp+"='"+theValue+"'");
  }
}
*/

// clears default text from a form element on click
function clear_descbox()
{
if (document.search.searchdesc.value == "restaurants")
document.search.searchdesc.value = "";
} 

function clear_namebox()
{
if (document.search.searchname.value == "waitrose")
document.search.searchname.value = "";
} 

// for Spry Blind effect to work

function MM_effectBlind(targetElement, duration, from, to, toggle)
{
	Spry.Effect.DoBlind(targetElement, {duration: duration, from: from, to: to, toggle: toggle});
}

//RUI - Constrain Event Images

 function setImgSize() {
  // declare the constrainst for the maximum height and width
  var maxH = 90;
  var maxW = 130;
  // get the collection of all images in the page
  var images = document.getElementsByTagName('IMG');
  // how many images to examine - assigning this make the comparison 
  // "cheaper" than referencing the length property for each iteration
  var last = images.length;
  for (var i = 0; i < last; i++) {
   // convenience reference to the ith images
   var currImg = images[i];
   // if the style class of the image is correct, adjust it
   if ('event_img' == currImg.className) {
    var h = currImg.height;
    var w = currImg.width;
    // pick whichever constraint is "harshest"
    var scale = Math.min(maxH/h, maxW/w);
    // scale the height and width
    currImg.height = Math.floor(scale*h);
    currImg.width = Math.floor(scale*w);
    currImg.style.display = 'block';
   }
  }
 }

 window.onload = setImgSize;

// RUI Image Resize for Plot Info Images

/*
 function setCaptionImgSize() {
  // declare the constraint for the maximum height and width
  var capImg = document.getElementById('captionimg');
  var parentDiv = capImg.parentNode;
  var w = parentDiv.offsetWidth;
  capImg.style.width = (w - 4) +'px';
 }

 window.onresize = setCaptionImgSize;
 window.onload = setCaptionImgSize;
*/



//aryooeye.StringUtil.0.0.0;r.0.0.0;richarduie[at]yahoo[dot]com;(c)2008 
if (!aryooeye) var aryooeye = new Function(); 
if (!aryooeye.StringUtil) 
{ 
aryooeye.StringUtil = 
function (args) { 
var whitespace = ' \n\r\t'; 
this.wrap = function(str, wid) { 
if (!wid < str.length) return str; 
return this.delimitBlocks(str, blockLen, '\n'); 
} 
this.drop = function(str, len) { 
if (!len) { 
var msg = 'MissingArgumentError: ' + 
this.className + '.drop()\n' + 
'object instance - ' + this.name + '\n' + 
'numeric argument {len} required'; 
throw new Error(msg); 
} 
if (!str) { 
var msg = 'MissingArgumentError: ' + 
this.className + '.drop()\n' + 
'object instance - ' + this.name + '\n' + 
'string argument {str} required'; 
throw new Error(msg); 
} 
if (len > str.length) return ''; 
if (0 > len) { 
return str.substring(0, str.length + len); 
} 
else return str.substring(len); 
} 
this.take = function(str, len) { 
if (!len) { 
var msg = 'MissingArgumentError: ' + 
this.className + '.take()\n' + 
'object instance - ' + this.name + '\n' + 
'numeric argument {len} required'; 
throw new Error(msg); 
} 
if (!str) { 
var msg = 'MissingArgumentError: ' + 
this.className + '.take()\n' + 
'object instance - ' + this.name + '\n' + 
'string argument {str} required'; 
throw new Error(msg); 
} 
if (0 < len) { 
if (len > str.length) { 
return this.padRight(str, len, ' '); 
} 
else return str.substring(0, len); 
} 
if (0 > len) { 
if (Math.abs(len) > str.length) { 
return this.padLeft(str, Math.abs(len), ' '); 
} 
else return str.substring(str.length + len); 
} 
return ''; 
} 
this.delimitListItems = function(strArray, delim) { 
if (!delim) delim = ','; 
var last = strArray.length - 1; 
var strList = ''; 
for (var j = 0; j < last; j++) { 
strList += strArray[j] + ', '; 
} 
return strList + strArray[last]; 
} 
this.delimitBlocks = function(str, blockLen, delim) { 
if (!delim) delim = ','; 
if (!blockLen) blockLen = 3; 
b = blockLen*-1; 
fstr = ''; 
while (0 < str.length) { 
fstr = delim + this.take(str, b) + fstr; 
str = this.drop(str, b); 
} 
return this.dLN(fstr, ' ' + delim); 
} 
this.padLeft = function(str, len, padChar) { 
if (!padChar) padChar = whitespace; 
return this.createPad(len - str.length, padChar) + str; 
} 
this.padRight = function(str, len, padChar) { 
if (!padChar) padChar = whitespace; 
return str + this.createPad(len - str.length, padChar); 
} 
this.createPad = function(len, padChar) { 
if (!padChar) padChar = whitespace; 
var pad = ''; 
for (var i = 0; i < len; i++) { 
pad += padChar; 
} 
return pad; 
} 
this.deleteLeadingNulls = function(str, nulls) { 
if (!nulls) nulls = whitespace; 
if (!str) { 
var msg = 'MissingArgumentError: ' + 
this.className + '.deleteLeadingNulls()\n' + 
'object instance - ' + this.name; 
throw new Error(msg); 
} 
var last = str.length; 
if (1 > last) return str; 
var i = 0; 
for (; i < last; i++) { 
if (!this.isIn(str.charAt(i), nulls)) break; 
} 
return str.substring(i); 
} 
this.dLN = function(str, nulls) { 
if (!nulls) nulls = whitespace; 
if (!str) { 
var msg = 'MissingArgumentError: ' + 
this.className + '.dLN()\n' + 
'object instance - ' + this.name; 
throw new Error(msg); 
} 
return this.deleteLeadingNulls(str, nulls); 
} 
this.deleteTrailingNulls = function(str, nulls) { 
if (!nulls) nulls = whitespace; 
if (!str) { 
var msg = 'MissingArgumentError: ' + 
this.className + '.deleteTrailingNulls()\n' + 
'object instance - ' + this.name; 
throw new Error(msg); 
} 
var last = str.length - 1; 
if (0 > last) return str; 
var i = last; 
for (; i > -1; i--) { 
if (!this.isIn(str.charAt(i), nulls)) break; 
} 
return str.substring(0, i+1); 
} 
this.dTN = function(str, nulls) { 
if (!nulls) nulls = whitespace; 
if (!str) { 
var msg = 'MissingArgumentError: ' + 
this.className + '.dTN()\n' + 
'object instance - ' + this.name; 
throw new Error(msg); 
} 
return this.deleteTrailingNulls(str, nulls); 
} 
this.deleteAllNulls = function(str, nulls) { 
if (!nulls) nulls = whitespace; 
if (!str) { 
var msg = 'MissingArgumentError: ' + 
this.className + '.deleteAllNulls()\n' + 
'object instance - ' + this.name; 
throw new Error(msg); 
} 
str = this.dLN(str, nulls); 
if (0 == str.length) return str; 
str = this.dTN(str, nulls); 
var last = str.length; 
if (1 > last) return str; 
var nstr = ''; 
for (var i = 0; i < last; i++) { 
if (!this.isIn(str.charAt(i), nulls)) { 
nstr += str.charAt(i); 
} 
} 
return nstr; 
} 
this.dAN = function(str, nulls) { 
if (!nulls) nulls = whitespace; 
if (!str) { 
var msg = 'MissingArgumentError: ' + 
this.className + '.dAN()\n' + 
'object instance - ' + this.name; 
throw new Error(msg); 
} 
return this.deleteAllNulls(str, nulls); 
} 
this.deleteExtraneousNulls = function(str, nulls) { 
if (!nulls) nulls = whitespace; 
if (!str) { 
var msg = 'MissingArgumentError: ' + 
this.className + '.deleteExtraneousNulls()\n' + 
'object instance - ' + this.name; 
throw new Error(msg); 
} 
str = this.dLN(str, nulls); 
if (0 == str.length) return str; 
str = this.dTN(str, nulls); 
var last = str.length - 1; 
if (0 > last) return str; 
var nstr = ''; 
for (var i = 0; i < last; i++) { 
if (!this.isIn(str.charAt(i), nulls) || 
 !this.isIn(str.charAt(i+1), nulls) ) { 
nstr += str.charAt(i); 
} 
} 
return nstr + str.charAt(last); 
} 
this.dEN = function(str, nulls) { 
if (!nulls) nulls = whitespace; 
if (!str) { 
var msg = 'MissingArgumentError: ' + 
this.className + '.dEN()\n' + 
'object instance - ' + this.name; 
throw new Error(msg); 
} 
return this.deleteExtraneousNulls(str, nulls); 
} 
this.trim = function(str) { 
return this.dLN(this.dTN(str)); 
} 
this.isIn = function(c, cSet) { 
if (!cSet) { 
var msg = 'MissingArgumentError: ' + 
this.className + '.isIn()\n' + 
'object instance - ' + this.name + '\n' + 
'argument {cSet} not given'; 
throw new Error(msg); 
} 
if (!c) { 
var msg = 'MissingArgumentError: ' + 
this.className + '.isIn()\n' + 
'object instance - ' + this.name + '\n' + 
'argument {c} not given'; 
throw new Error(msg); 
} 
var last = cSet.length; 
if (1 > last) { 
var msg = 'ArgumentLengthError: ' + 
this.className + '.isIn()\n' + 
'object instance - ' + this.name + '\n' + 
'argument {cSet} must contain characters'; 
throw new Error(msg); 
} 
if (1 != c.length) { 
var msg = 'ArgumentLengthError: ' + 
this.className + '.isIn()\n' + 
'object instance - ' + this.name + '\n' + 
'argument {c} must contain exactly 1 character'; 
throw new Error(msg); 
} 
return -1 != cSet.indexOf(c); 
} 
this.isLower = function(c) { 
return c == c.toLowerCase(); 
} 
this.isUpper = function(c) { 
return c == c.toUpperCase(); 
} 
this.getClassName = function() { 
return 'StringUtil'; 
} 
this.name = '_name_not_set_'; 
this.className = this.getClassName(); 
} 
} 
//	varStringUtil=newaryooeye.StringUtil(); 
; 


//aryooeye.PopupDivManager;r.0.0.0;richarduie[at]yahoo[dot]com;(c)2008

/////////////////////////////////////////////////////////////////////////
//                                                                     //
//   Manage popup DIVs dynamically using JavaScript object prototype   //
//                                                                     //
/////////////////////////////////////////////////////////////////////////
//                                                                     //
//   RUI library member that enforces containment under "aryooeye"     //
//   namespace; offers pseudo-static reference options for public      //
//   members via name by dot(.)-references to members that can rely    //
//   on "instantiation" calls to default, no-argument constructor.     //
//                                                                     //
/////////////////////////////////////////////////////////////////////////
//                                                                     //
//   Filename.......PopupDivManager.js                                 //
//   Author.........Richard Harrison (richarduie[at]yahoo[dot]com)     //
//   Created On.....2008-01-19                                         //
//   Last Revised...2008-01-31                                         //
//                                                                     //
/////////////////////////////////////////////////////////////////////////

/**
 *  @Object: PopupDivManager
 *
 *
 *  @Syntax: var popDivMgr = new aryooeye.PopupDivManager()
 *           PopupDivManager.{method_name}() [static]
 *
 *  @Goals:  add popup DIVs on-the-fly
 *
 *  NOTE.....this is a very lightweight implementation to 
 *           keep the bandwidth requirements small - the 
 *           popup containers are DIV elements and, thus, 
 *           can contain any other type of HTML element - 
 *           however, there is no built-in defense against 
 *           the "bleed-through" of window-class elements, 
 *           e.g., select controls, in IE6 - if such 
 *           protection is required, try one of the heavy-
 *           weight implementations, such as the YUI 
 *           container/ovelay module.
 */


/////////////////////////////////////////////////////////////////////
//   N A M E S P A C E   C O N T A I N E R   O V E R H E A D
//
//   Enforce the condition that any RUI object can only be
//   created under the namespace aryooeye in order to further
//   ensure protection from potential name-collisions.
//
	// If namespace object does not yet exist, create it.
	if ('undefined' == typeof aryooeye) var aryooeye = new Function();
	// If object has already been attached, exit.
	if ('undefined' == typeof aryooeye.PopupDivManager)
{	// open conditional object creation
	// Now add current object to aryooeye namespace.
	aryooeye.PopupDivManager =


function PopupDivManager ()
{
	//////////////////////////////////////////////////////////////////
	//  D E P E N D E N C Y   M A N A G E M E N T  ///////////////////
	//	 ...no current dependencies...

	//////////////////////////////////////////////////////////////////
	//  P R I V A T E   M E M B E R S  ///////////////////////////////
		// Declare private methods.
			function register(puid, pud) {
			// register associative index (key) for popup (div) -
			// note - key will be id of div element in page context
				puArray[puid] = pud;
			}

			function addCloser(content, puid, name) {
			// for persistent popups that are not closed in response to some other event,
			// provide a fairly obvious "close" idiom to allow user to close the popup
			// manually - place a click-sensitive "X" on the popup to allow user to
			// close the popup manually
				var cs = closerStyle;	// convenience reference to style for closer [X]
				// convert font-size of closer [X] to integer
				var fs = parseInt(cs.substring(cs.indexOf('font-size:') + 'font-size:'.length));
				var p = parseInt(padding);					// convert padding to integer
				// reduce available width for content by font-size of closer [X] and
				// padding of container div
				var w = (width - fs - p) + 'px';			// calcuate width for content
				// left placement for closer [X] puts right margin of [X] 2px from right-
				// hand border of container (top is 2px as well - statically declared)
				var l = (width - fs + p - 2) + 'px';	// calculate left for "button"
				// add HTML for closer to the content for the popup
				var c = '' +
					'<div style="width: ' + w + ';">' + content + '</div>' 	+
					'<div style="' + cs + ' left: ' + l + ' ;" ' 					+
						'onclick="' + name + '.hidePopup(\'' + puid + '\');">X</div>'		;
				return c;
			}

			function chkParms(puid, c, w, h, l, t, x) {
			// check parameters and set internal values accordingly
			// return true, if all's well - otherwise false
				if (!puid || !c) return false;	// exit, if container id or content missing
				content = c;							// set content to that requested
				width = ((!w)?300:w) + 'px';		// set width to that requested, with default
				height = ((!h)?300:h) + 'px';		// set height to that requested, with default
				left = ((!l)?300:l) + 'px';		// set left to that requested, with default
				top = ((!t)?300:t) + 'px';			// set top to that requested, with default
				// set indicator of whether div will have a "closer" element, default to true
				hasCloser = (!x && false != x)?true:x;
				return true;	// good exit
			}

		// Declare private fields.
			// - publicly gettable and settable
			//  style attributes for popup - initialize with defaults
			var backgroundColor = '#EEE';
			var borderColor = 'black';
			var borderStyle = 'solid';
			var borderWidth = '2px';
			var color = '#48A';
			var fontFamily = 'Arial, sans-serif';
			var fontSize = '14px';
			var fontWeight = 'bold';
			var margin = 0;
			var padding = '6px';
			var position = 'absolute';
			var textAlign = 'left';
			var zIndex = 9;
			var highestZ = 9;

			var hasCloser;					// Boolean to indicate whether popup has a closer [X] control
			var puArray = new Array();	// puArray to store popups

			var name = 'pdm';				// default name for object - reset as needed to avoid name-collisions

			// set style attributes for closer control, in case requested
			var closerStyle = '' +
				'background-color: white; '			+
				'border: 2px solid red; ' 				+
				'color: red; '								+
				'cursor:pointer; '						+
				'font-family: Arial, sans-serif; '	+
				'font-size: 10px; '						+
				'font-weight: bold; '					+
				'margin: 0; '								+
				'padding: 0 0 1px 1px; '				+
				'position: absolute; '					+
				'top: 2px; '								+
				'text-align: center; '					+
				'width: 10px; '							;

			var content, width, height, left, top;	// no default values for these

			// - publicly gettable only

	//////////////////////////////////////////////////////////////////
	//  P U B L I C   M E M B E R S  /////////////////////////////////
		// Declare public methods.
			// - accessors and mutators...privileged updates of private fields
			//  use of any of the setters will override previous settings with
			//  new values that will be used for any new popups created after
			//  the change - existing, registered popups are not affected
			this.getBgColor = function() { return backgroundColor; }
			this.setBgColor = function(b) { backgroundColor = b; }

			this.getBorderColor = function() { return borderColor; }
			this.setBorderColor = function(b) { borderColor = b; }

			this.getBorderStyle = function() { return borderStyle; }
			this.setBorderStyle = function(b) { borderStyle = b; }

			this.getBorderWidth = function() { return borderWidth; }
			this.setBorderWidth = function(b) { borderWidth = b; }

			this.getCloserStyle = function() { return closerStyle; }
			this.setCloserStyle = function(s) { closerStyle = s; }

			this.getColor = function() { return color; }
			this.setColor = function(c) { color = c; }

			this.getContent = function() { return content; }
			this.setContent = function(c) { content = c; }

			this.getFontFamily = function() { return fontFamily; }
			this.setFontFamily = function(f) { fontFamily = f; }

			this.getFontSize = function() { return fontSize; }
			this.setFontSize = function(f) { fontSize = f; }

			this.getFontWeight = function() { return fontWeight; }
			this.setFontWeight = function(f) { fontWeight = f; }

			this.getHasCloser = function() { return hasCloser; }
			this.setHasCloser = function(h) { hasCloserStyle = h; }

			this.getHeight = function() { return height; }
			this.setHeight = function(h) { height = h; }

			this.getLeft = function() { return left; }
			this.setLeft = function(l) { left = l; }

			this.getName = function() { return name; }
			this.setName = function(n) { name = n; }

			this.getPadding = function() { return padding; }
			this.setPadding = function(p) { padding = p; }

			this.getTop = function() { return top; }
			this.setTop = function(l) { top = t; }

			this.getWidth = function() { return width; }
			this.setWidth = function(w) { width = w; }

			this.getZIndex = function() { return zIndex; }
			this.setZIndex = function(z) { zIndex = z; }

			// - control methods
			this.createPopup = function(puid, c, w, h, l, t, x) {
			// create the popup and assign its properties
				if (!chkParms(puid, c, w, h, l, t, x)) return false;
				if (puArray[puid]) this.destroyPopup(puid);
				var DIV = document.createElement('DIV');
				DIV.id = puid;
				DIV.innerHTML = (hasCloser)?addCloser(content, puid, this.getName()):content;
				DIV.style.backgroundColor = backgroundColor;
				DIV.style.borderColor = borderColor;
				DIV.style.borderStyle = borderStyle;
				DIV.style.borderWidth = borderWidth;
				DIV.style.color = color;
				DIV.style.display = 'none';			// intitially, don't show popup
				DIV.style.fontFamily = fontFamily;
				DIV.style.fontSize = fontSize;
				DIV.style.fontWeight = fontWeight;
				DIV.style.left = left;
				DIV.style.margin = margin;
				DIV.style.padding = padding;
				DIV.style.position = position;
				DIV.style.textAlign = textAlign;
				DIV.style.top = top;
				DIV.style.width = width;
				DIV.style.zIndex = zIndex;
				document.body.appendChild(DIV);		// add element to body of document
				register(puid, DIV);						// record id and element
				return true;
			}

			this.showPopup = function(puid) {
				try {
					document.getElementById(puid).style.display = 'block';
					return true;
				}
				catch (e) {	return false;}
			}

			this.hidePopup = function(puid) {
				try {
					document.getElementById(puid).style.display = 'none';
					return true;
				}
				catch (e) {	return false;}
			}

			this.destroyPopup = function(puid) {
				var d = document.getElementById(puid);
				try {
					document.body.removeChild(d);
				}
				catch (e) {;}
				register(puid, null);
			}

			this.doPopup = function(puid, c, w, h, l, t, x) {
			// convenience method to both create and show popup with current
			// properties, except for those specified in parameters
				if (this.createPopup(puid, c, w, h, l, t, x)) {
					this.showPopup(puid);
					return true;
				}
				else return false;
			}

			this.hideAllPopups = function() {
			// hide all popups currently under management
				for(key in puArray) {
					this.hidePopup(key);
				}
			}
			// Declare public fields.

	//////////////////////////////////////////////////////////////////
	//  C O N S T R U C T O R  ///////////////////////////////////////
		// Construction steps - only run at instantiation.
		// ...no differential construction required at present...
}

}	// close conditional object creation

/////////////////////////////////////////////////////////////////////
//   S U P P O R T    P S E U D O - S T A T I C    C L A S S -
//   S T Y L E    R E F E R E N C E S
	//	Since constructor supports default, no-argument instantiation,
	// provide a "static" reference version to the public members.
	// Note that this removes rui namespace insulation against name-
	// collisions; developer is responsible for managing name-safety
	// in implementation context. Next statement can be commented or
	// de-commented without affecting base object in any way.
//	var PopupDivManager = new aryooeye.PopupDivManager();

//aryooeye.ValidationManager;r.0.0.0;richarduie[at]yahoo[dot]com;(c)2008

/////////////////////////////////////////////////////////////////////////
//                                                                     //
//   validation message management using JavaScript object prototype   //
//                                                                     //
/////////////////////////////////////////////////////////////////////////
//                                                                     //
//   RUI library member that enforces containment under "aryooeye"     //
//   namespace; offers pseudo-static reference options for public      //
//   members via name by dot(.)-references to members that can rely    //
//   on "instantiation" calls to default, no-argument constructor.     //
//                                                                     //
/////////////////////////////////////////////////////////////////////////
//                                                                     //
//   Filename.......ValidationManager.js                               //
//   Author.........Richard Harrison (richarduie[at]yahoo[dot]com)     //
//   Created On.....2007-01-31                                         //
//   Last Revised...2008-01-31                                         //
//                                                                     //
/////////////////////////////////////////////////////////////////////////

/**
 *  @Object: ValidationManager
 *
 *
 *  @Syntax: var valMgr = new aryooeye.ValidationManager()
 *           ValidationManager.{method_name}() [static]
 *
 *  @Goals:  add or apply validation to page elements
 */


/////////////////////////////////////////////////////////////////////
//   N A M E S P A C E   C O N T A I N E R   O V E R H E A D
//
//   Enforce the condition that any RUI object can only be
//   created under the namespace aryooeye in order to further
//   ensure protection from potential name-collisions.
//
	// If namespace object does not yet exist, create it.
	if ('undefined' == typeof aryooeye) var aryooeye = new Function();
	// If object has already been attached, exit.
	if ('undefined' == typeof aryooeye.ValidationManager)
{	// open conditional object creation
	// Now add current object to aryooeye namespace.
	aryooeye.ValidationManager =

function ValidationManager() 

{
	//////////////////////////////////////////////////////////////////
	//  D E P E N D E N C Y   M A N A G E M E N T  ///////////////////
	//  aryooeye.StringUtil
	//  aryooeye.PopupDivManager

	//////////////////////////////////////////////////////////////////
	//  P R I V A T E   M E M B E R S  ///////////////////////////////
		// Declare private methods.
		// convenience function
		function get(eid) { return document.getElementById(eid); }

		function composeBadCharMsg(msgStub, badChars) {
			var tail = '';
			// if only one bad character report it
			if (1 == badChars.length) tail = ': ' + badChars;
			// ...otherwise, report a comma-delimited list of the bad characters
			else tail = 's: ' + strUtil.delimitListItems(badChars.split(''));
			return msgStub + tail;
		}
	
		function register(pid, item) {
		// record association of error messages with corresponding items
			msgRegistry[pid] = item;
		}

		function setSnap() {
			var cmd = 'window.onresize = ' + name + '.snapToItems';
			// this must be set into external document frame of calling stack 
			// in order to become available for call as an event-handler from 
			// outside - no delay required...won't be "instantaeous," but 
			// should easily happen before user can resize window
			setTimeout(cmd, 0);
			isSnapSet = true;	// won't need to happen again
		}

		// Declare private fields.
			var strUtil = new aryooeye.StringUtil();
			var msgRegistry = new Array();
			var isSnapSet = false;
			var isIE = -1 != navigator.userAgent.indexOf('MSIE');
			var ieHeightScalar = 1.8;

			var name = 'vm';	// default name for object - reset as needed to avoid name-collisions

			// - publicly gettable and settable
			// string array of valid domain suffixes
			var domainSuffixArray = [
				'ac','ad','ae','aero','af','ag','ai','al','am','an','ao','aq','ar','arpa','as','at','au','aw','az',
				'ba','bb','bd','be','bf','bg','bh','bi','biz','bj','bm','bn','bo','br','bs','bt','bv','bw','by','bz',
				'ca','cc','cf','cg','ch','ci','ck','cl','cm','cn','co','com','coop','cr','cs','cu','cv','cx','cy','cz',
				'de','dj','dk','dm','do','dz',
				'ec','edu','ee','eg','eh','er','es','et','eu',
				'fi','firm','fj','fk','fm','fo','fr','fx',
				'ga','gb','gd','ge','gf','gh','gi','gl','gm','gn','gov','gp','gq','gr','gs','gt','gu','gw','gy',
				'hk','hm','hn','hr','ht','hu',
				'id','ie','il','in','info','int','io','iq','ir','is','it',
				'jm','jo','jobs','jp',
				'ke','kg','kh','ki','km','kn','kp','kr','kw','ky','kz',
				'la','lb','lc','li','lk','lr','ls','lt','lu','lv','ly',
				'ma','mc','md','mg','mh','mil','mk','ml','mm','mn','mo','mp','mq','mr','ms','mt','mu','museu','mv','mw','mx','my','mz',
				'na','name','nato','nc','ne','net','nf','ng','ni','nl','no','nom','np','nr','nt','nu','nz',
				'om','org','pa',
				'pe','pf','pg','ph','pk','pl','pm','pn','pr','pro','pt','pw','py',
				'qa',
				're','ro','ru','rw',
				'sa','sb','sc','sd','se','sg','sh','si','sj','sk','sl','sm','sn','so','sr','st','store','su','sv','sy','sz',
				'tc','td','tf','tg','th','tj','tk','tm','tn','to','tp','tr','trave','tt','tv','tw','tz',
				'ua','ug','uk','um','us','uy',
				'va','vc','ve','vg','vi','vn','vu',	
				'web','wf',	'ws',	
				'ye',	'yt',	'yu',	
				'za',	'zm',	'zr','zw'
			]

			// set default characters used to validate semantic types
			var emailChars = 'abcdefghijklmnopqrstuvwxyz';
				emailChars += emailChars.toUpperCase(nameChars) + '0123456789@.-_';
			var nameChars = 'abcdefghijklmnopqrstuvwxyz';
				nameChars += nameChars.toUpperCase(nameChars) + '-\'';
			var numeralChars = '0123456789.-';
			var phoneChars = '0123456789-';
			var zipChars = '0123456789';
			var zip4Chars = '0123456789-';
			var passChars = nameChars + numeralChars;

	//////////////////////////////////////////////////////////////////
	//  P U B L I C   M E M B E R S  /////////////////////////////////
		// Declare public methods.
			// - accessors and mutators...privileged updates of private fields
			//  use of any of the setters will override previous settings with
			//  new values that will be used for all future calls
			this.getEmailChars = function() { return emailChars; }
			this.setEmailChars = function(e) { emailChars = e; }

			this.getNameChars = function() { return nameChars; }
			this.setNameChars = function(n) { nameChars = n; }

			this.getNumeralChars = function() { return numeralChars; }
			this.setNumeralChars = function(n) { numeralChars = n; }

			this.getPhoneChars = function() { return phoneChars; }
			this.setPhoneChars = function(p) { phoneChars = p; }

			this.getZipChars = function() { return zipChars; }
			this.setZipChars = function(z) { zipChars = z; }

			this.getZip4Chars = function() { return zip4Chars; }
			this.setZip4Chars = function(z) { zip4Chars = z; }

			this.getName = function() { return name; }
			this.setName = function(n) { name = n; }

			this.getIeHeightScalar = function() { return ieHeightScalar; }
			this.setIeHeightScalar = function(i) { ieHeightScalar = i; }


			// - general validation utilities
			this.isInList = function(item, list) {
				var is = false;
				var last = list.length;
				for (var j = 0; j < last; j++) {
					is = is || item == list[j];
					if (is) break;
				}
				return is;
			}


			// - validation of strings with semantic types
			this.validateEmail = function(email, cset) {
			// if only validation and potentially corresponding error message are required, 
			// this method may be called directly - empty, string return indicates "good"
				var msg = '';		// initialize message to indicate "no problems"
				if (0 == email.length) msg = 'email address missing';
				// ...otherwise, check content and structure
				else {
					if (!cset) cset = emailChars;		// use default, if none specified
					// throw out all valid characters from email address
					var badChars = strUtil.dAN(email, cset);
					// check for remaining, invalid characters
					if (0 != badChars.length) {
						// set base text for error message
						msg = 'email address contains invalid character';
						// if only one bad character report it
						if (1 == badChars.length) msg += ': ' + badChars;
						// ...otherwise, report a comma-delimited list of the bad characters
						else msg += 's: ' + strUtil.delimitListItems(badChars.split(''));
					}
					// check for missing @ sign
					else if (-1 == email.indexOf('@')) {
						msg = 'missing [at] in email address';
					}
					// check for missing . in domain name
					else if (-1 == email.indexOf('.')) {
						msg = 'missing [dot] in email address';
					}
					// verify that @ sign follows at least one preceding character
					else if (0 == email.indexOf('@')) {
						msg = 'email address can\'t start with the @ sign';
					}
					// verify that the domain suffix is valid, e.g., com, edu, etc.
					else if (!this.isInList(email.substring(1 + email.lastIndexOf('.')), domainSuffixArray) ) {
						var s = email.substring(1 + email.lastIndexOf('.'));
						if (0 == s.length) msg = 'missing domain suffix for email address';
						else msg = s + ' is not a valid domain suffix for an email address';
					}
				}
				return msg;	// advise caller of result
			}

			this.validatePass = function(pass, cset) {
			// if only validation and potentially corresponding error message are required, 
			// this method may be called directly - empty, string return indicates "good"
				var msg = '';		// initialize message to indicate "no problems"
				if (0 == pass.length) msg = 'password missing';
				else if (8 > pass.length || 16 < pass.length) msg = 'password must be 8 to 16 characters';
				// ...otherwise, check content and structure
				else {
					if (!cset) cset = passChars;		// use default, if none specified
					// throw out all valid characters from name
					var badChars = strUtil.dAN(pass, cset);
					// check for remaining, invalid characters
					if (0 != badChars.length) {
						msg = composeBadCharMsg('password contains invalid character', badChars);
					}
				}
				return msg;
			}

			this.validateName = function(name, cset) {
			// if only validation and potentially corresponding error message are required, 
			// this method may be called directly - empty, string return indicates "good"
				var msg = '';		// initialize message to indicate "no problems"
				if (0 == name.length) msg = 'name missing';
				// ...otherwise, check content and structure
				else {
					if (!cset) cset = nameChars;		// use default, if none specified
					// throw out all valid characters from name
					var badChars = strUtil.dAN(name, cset);
					// check for remaining, invalid characters
					if (0 != badChars.length) {
						msg = composeBadCharMsg('name contains invalid character', badChars);
					}
				}
				return msg;
			}

			this.validatePhone = function(phone, cset) {
			// if only validation and potentially corresponding error message are required, 
			// this method may be called directly - empty, string return indicates "good"
				var msg = '';		// initialize message to indicate "no problems"
				if (0 == phone.length) msg = 'phone number missing';
				// ...otherwise, check content and structure
				else {
					if (!cset) cset = phoneChars;		// use default, if none specified
					// throw out all valid characters from phone number
					var badChars = strUtil.dAN(phone, cset);
					// check for remaining, invalid characters
					if (0 != badChars.length) {
						msg = composeBadCharMsg('phone number contains invalid character', badChars);
					}
					// verify conformance to format
					else if ('-' != phone[3] || '-' != phone[7] || 
						10 != (strUtil.dAN(phone, '-')).length) {
						msg = 'phone number must be like: 999-999-9999';
					}
				}
				return msg;
			}

			this.validateZip = function(zip, cset) {
			// if only validation and potentially corresponding error message are required, 
			// this method may be called directly - empty, string return indicates "good"
				var msg = '';		// initialize message to indicate "no problems"
				if (0 == zip.length) {
					msg = 'zip code missing';
				}
				// ...otherwise, check content and structure
				else {
					if (!cset) cset = zipChars;
					// throw out all valid characters from zip
					var badChars = strUtil.dAN(zip, cset);
					// check for remaining, invalid characters
					if (0 != badChars.length) {
						msg = composeBadCharMsg('zip code contains invalid character', badChars);
					}
					// verify length
					else if (5 != zip.length) {
						msg = 'zip code must be like: 99999';
					}
				}
				return msg;
			}

			this.validateZip4 = function(zip, cset) {
			// if only validation and potentially corresponding error message are required, 
			// this method may be called directly - empty, string return indicates "good"
				var msg = '';		// initialize message to indicate "no problems"
				if (0 == zip.length) msg = 'zip code missing';
				// ...otherwise, check content and structure
				else {
					// throw out all valid characters from zip+4
					if (!cset) cset = zip4Chars;
					// check for remaining, invalid characters
					var badChars = strUtil.dAN(zip, cset);
					if (0 != badChars.length) {
						msg = composeBadCharMsg('zip code +4 contains invalid character', badChars);
					}
					// verify conformance to format
					else if ('-' != zip[5] || 9 != (strUtil.dAN(zip, '-')).length) {
						msg = 'zip code +4 must be like: 99999-9999';
					}
				}
				return msg;
			}

			// - form validation
			this.validateForm = function(fid) {
			// step through the inputs of a form, validating each by type
				var msg = '';					// initialize to indicate "no problem"
				var valid = true;
				var f = get(fid);				// get convenience reference to form
				var last = f.length;			// how many children of form?
				for (var i = 0; i < last; i++) {
					var item = f[i];			// get pointer to current child item
					switch (item.type) {		// branch control by input type
						case 'button': {
							continue;			// nothing at this time
						}
						case 'checkbox': {
							continue;			// nothing at this time
						}
						case 'radio': {
							continue;			// nothing at this time
						}
						case 'select': {
							continue;			// nothing at this time
						}
						case 'password': 		// same rules for password and text
						case 'text': {
							// item should have one or more of semantic type names 
							// assigned to its class attribute - if multiple, types 
							// are given, each validation will be run until one 
							// fails - semantic classes begin with 'ruivm'
							var className = item.className.split(',');
							var lastCN = className.length;
							for(var j = 0; j < lastCN; j++) {
								// check each class name for possibility that it is 
								// aryooeye.ValidationManager (ruivm) semantic class, 
								// and, if so, pass for validation
								if (-1 != className[j].indexOf('ruivm')) {
									valid = valid && this.validateTextItem(item, true, null, className[j]);
								}
							}
						}
						case 'textarea': {
							continue;	// nothing at this time
						}
					}
				}
				return valid;
			}

			this.validateTextItem = function(item, forceFocus, targetId, className) {
			// validate contents and structure of string content of text inputs
			// by giving ruivm prefixed semantic classes to elements to be validated and 
			// passing all validation calls here, messages are registered for ongoing 
			// management - individual validation methods may be be called directly, if 
			// this is not required
				// register window resize event-handler, if not yet done
				if (!isSnapSet && null == targetId) setSnap();
				// if method called directly, not all arguments mayhave been given - 
				// in that case, presume that semantic class is in first position, if 
				// more than one class is provided
				if (!className) {
					className = item.className;
					// comma-delimited list indicates multiple classes
					if (-1 != className.indexOf(',')) {
						// parse first class name from list
						className = className.substring(0, className.indexOf(','));
					}
				}
				if ('undefined' == typeof forceFocus) forceFocus = true;
				if ('undefined' == typeof targetId) targetId = null;
				var pid = '_ruivm_' + item.id;	// create page id for new message
				var msg = '';							// initialize message to indicate "no problem"
				var valid = true;						// initialize validation switch to "good"
				// do the validation by semantic class
				switch (className) {
					case 'ruivmEmail': {
						msg = this.validateEmail(item.value);
						break;
					}
					case 'ruivmPass': {
						msg = this.validatePass(item.value);
						break;
					}
					case 'ruivmName': {
						msg = this.validateName(item.value);
						break;
					}
					case 'ruivmPhone': {
						msg = this.validatePhone(item.value);
						break;
					}
					case 'ruivmZip': {
						msg = this.validateZip(item.value);
						break;
					}
					case 'ruivmZip4': {
						msg = this.validateZip4(item.value);
						break;
					}
				}
				// if there is a non-empty message, there is a problem
				if (0 < msg.length) {
					valid = false;		// set return to advise caller
					if (null == targetId) {
						var el = get(item.id);				// get convenience reference to element
						// get top and left positions of element relative to its immediate parent
						// if needed, use popMgr's font-size for the IE correction here, since the 
						// message doesn't yet exist and will be created with popMgr's current value 
						// of font-size get left position of element
						var t = el.offsetTop;
						var l = el.offsetLeft + (isIE?(parseInt(this.popMgr.getFontSize())):0);
						// get height of element
						var h = el.offsetHeight + (isIE?(ieHeightScalar*parseInt(this.popMgr.getFontSize())):0);
						var w = el.offsetWidth;				// get width of element
						// create a popup div to contain to message
						this.popMgr.doPopup(pid, msg, null, null, l, t + h, false);
					}
					else {
						document.getElementById(targetId).innerHTML = msg;
					}
					if (forceFocus) {
						// item.focus() isn't guaranteed to work for direct calls - 
						// set timer call into page frame of calling stack
						var cmd = "document.getElementById('" + item.id + "').focus()";
						setTimeout(cmd, 100);
					}
					// record message and corresponding item to which it pertains
					register(pid, item);
				}
				else {
					if (null == targetId) {
						// ...otherwise, all is well - remove any existing message/item 
						// association from registry
						this.popMgr.destroyPopup('_ruivm_' + item.id);
						register(pid, null);
					}
					else {
						document.getElementById(targetId).innerHTML = '&nbsp;';
					}
				}

				return valid;	// tell caller about state
			}

			this.snapToItems = function() {
			// event-handler for window resize events - for all of the outstanding 
			// error messages, move them to positions that keep the asscociation 
			// of the message to its corresponding item  visually unambiguous
				for (key in msgRegistry) {
					// get reference to current message
					var msg = document.getElementById(key);
					// get reference to item associated with current message
					try {
						var item = document.getElementById(msgRegistry[key].id);
					}
					catch (e) {
						return;
					}
					var h = item.offsetHeight;			// get item's height
					// if needed, use message's actual font-size for IE corrections here - 
					// popMgr's value may have been changed, since this item was created
					// get left position of element
					var l = item.offsetLeft + (isIE?(parseInt(msg.style.fontSize)):0);
					// get height of element
					var h = item.offsetHeight + (isIE?(ieHeightScalar*parseInt(msg.style.fontSize)):0);
					var t = item.offsetTop;				// get item's top position
					msg.style.left = l + 'px';			// update message's left position
					msg.style.top = (h + t) + 'px';	// update message's top position
				}
			}

			// make public, so that default display attributes may altered, if desired
			this.popMgr = new aryooeye.PopupDivManager();
				this.popMgr.setColor('red');
				this.popMgr.setBgColor('transparent');
				this.popMgr.setBorderColor('transparent');
				this.popMgr.setFontSize('9px');
				this.popMgr.setPadding(0);

			// general functions - - - - - - - - - - - - - - - - - -

			this.getClassName = function() {
					return 'ValidationManager';
			}

		// Declare public fields.
			// in case instance needs to know its name, set it directly,
			// after instantiation, i.e., {instance}.name = '{name}' -
			// this is purely an optional, convenience field, which
			// could be attached independent of this definition, but is
			// declared here with a default value for possible use in
			// the report() method
			// set default value - may be used by report()
			this.name = '_name_not_set_';

			// provide dot referencable field of standard property name - can
			// be overridden, but will be refreshed to actual name of "class,"
			// if getter is caller
			this.className = this.getClassName();


	//////////////////////////////////////////////////////////////////
	//  C O N S T R U C T O R  ///////////////////////////////////////
		// Construction steps - only run at instantiation.
		// ...no differential construction required at present...
}

}

/////////////////////////////////////////////////////////////////////
//   S U P P O R T    P S E U D O - S T A T I C    C L A S S - 
//   S T Y L E    R E F E R E N C E S
	//	Since constructor supports default, no-argument instantiation, 
	// provide a "static" reference version to the public members.
	// Note that this removes rui namespace insulation against name-
	// collisions; developer is responsible for managing name-safety 
	// in implementation context. Next statement can be commented or 
	// de-commented without affecting base object in any way.
//	var ValidationManager = new aryooeye.ValidationManager();

//browser sniff

var isIE6 = -1 != navigator.userAgent.indexOf('MSIE 6');
		var popMgr = new aryooeye.PopupDivManager();		// create instance for page
		var valMgr = new aryooeye.ValidationManager();	// create instance for page
			valMgr.setName('valMgr');							// override default instance name
			valMgr.popMgr.setBorderWidth(0);					// no borders for errors in demo
			if (isIE6) valMgr.setIeHeightScalar(0);

		// associative array for terms (keys) and definitions (values)
		var definitions = new Array();
		definitions['highlight'] = 'to display in a different color; to enhance salience relative to context';
		definitions['definition'] = 'list of attributes; description of properties';

		// convenience function
		function get(eid) { return document.getElementById(eid); }

		// for mouseover events on defined terms, show definitions
		function showDefn(eid) {
			var did = 'defn' + eid;
			if (get(did)) popMgr.showPopup(did);	// if already created, simply show it
			else {											// ...otherwise create and show it
				var isIE = -1 != navigator.userAgent.indexOf('MSIE');
				var defn = definitions[eid];
				var el = get(eid);
				var t = el.offsetTop;
				var l = el.offsetLeft;
				var h = el.offsetHeight*((isIE6 || isIE)?1:2);
				var w = el.offsetWidth;
				popMgr.doPopup(did, defn, null, null, l + (Math.floor(w/2)), t + h, false);
			}
		}

		// for mouseout events on defined terms, hide definitions
		function hideDefn(eid) {
			popMgr.hidePopup('defn' + eid);
		}

		function chkSubmit(formId, fids, msgTargets) {
			var isValid = true;
			var last = fids.length;
			for (var i = 0; i < last; i++) {
				var f = document.getElementById(fids[i]);
				var val = valMgr.validateTextItem(f, false, msgTargets[i]);
				isValid = isValid && val;
			}
			if (isValid) document.getElementById(formId).submit();
			return isValid;
		}

		//Profile.php page: If user clicks delete classified ad or review
		function confirmDelete(delUrl) {
			if (confirm("Are you sure you want to delete")) {
				document.location = delUrl;
			}
		}
		
		var pdm; // declare global to page, so closer [x] can reference by name
		// manage popup div for display of entire all-zones map from the context
		// of the zone-veiw map page -- manage all actions under this closure, 
		// the PopupDivManager and its behavior is currently currently used in 
		// this fashion only in the zone.php -- NOTE: particular changes to the 
		// borders may not be general to all usages, if other cases arise
		function popFullMap() {
			var isIE = -1 != navigator.userAgent.indexOf('MSIE');
			pdm = new aryooeye.PopupDivManager();

			// new code to manage page masking for map display starts here - - - - -
			// add mask div to page in script code to avoid having to update every page on the site
			var mask = document.createElement('DIV');
			mask.id = 'mapMask';
			document.body.appendChild(mask);

			// extend base prototype to handle page masking when map is displayed
			pdm.doMask = function(onOff) {
				var el = document.getElementById('mapMask');
				el.style.height = '100%'
				el.style.width = '100%';
				el.style.display = ('on' == onOff)?'block':'none';
			}
			// override base prototype functions for hide and show to add mask handling
			pdm.hidePopup = function(puid) {
				try {
					document.getElementById(puid).style.display = 'none';
					this.doMask('off');
					return true;
				}
				catch (e) {	
					return false;
				}
			}
			pdm.showPopup = function(puid) {
				try {
					document.getElementById(puid).style.display = 'block';
					this.doMask('on');
					return true;
				}
				catch (e) {	
					return false;
				}
			}
			// new code to manage page masking for map display ends here - - - - - -

			// in case previously created (in global scope) and window resized since; 
			// could be more simply managed, if the popup was potentially needed in 
			// every page, but since this is only used in the zones.php, this one 
			// function absolutely manages the single, global, variable {pdm} that 
			// take no content in all other contexts to which global.js is included
			pdm.destroyPopup('bigMap');
			// reset border attributes from defaults before creating popup
			pdm.setBorderColor('#B0B');
			pdm.setBorderWidth('3px');

			// create non-default styles for the closer {x} subdiv on the popup
			var cStyle = '' +
				'background-color: white; ' +
				'border: 2px solid #B0B; ' +
				'color:  #B0B; ' +
				'cursor:pointer; ' +
				'font-family: Arial, sans-serif; ' +
				'font-size: 10px; ' +
				'font-weight: bold; ' +
				'left: 958px; ' +
				'margin: 2px; ' +
				// padding is 1px -left for IE, 1px -right for non-IE...go figure!
				'padding:' + ((isIE)?'0 0 0 1px':'0 1px 0 0') + '; ' +
				'position: absolute; ' +
				'top: 2px; ' +
				'text-align: center; ' +
				'width: 10px; ' +
				'top: 2px;' ;
			pdm.setCloserStyle(cStyle);

			var content = '' +
			'<img src ="images/map/full_map.jpg" width ="950" height ="409" alt="overview map" usemap ="#bigMapZones" border="0" />' +
			
			'<map id ="bigMapZones" name="bigMapZones">' +
			'	<area shape ="poly" coords ="650,146,704,188,690,220,594,220,594,196,630,182"' +
			'		href ="http://www.discoverecclesall.co.uk/zones.php?zone=1"' +
			'		alt="" />' +
			'	<area shape ="poly" coords ="512,148,536,148,556,182,588,198,588,220,476,220,466,194"' +
			'		href ="http://www.discoverecclesall.co.uk/zones.php?zone=2"' +
			'		alt="" />' +
			'	<area shape ="poly" coords ="298,236,360,236,390,280,446,280,470,300,484,300,486,318,604,318,610,350,424,350"' +
			'		href ="http://www.discoverecclesall.co.uk/zones.php?zone=3"' +
			'		alt="" />' +
			'	<area shape ="poly" coords ="358,104,546,104,536,132,506,132,454,182,418,170,380,184,360,166,366,130"' +
			'		href ="http://www.discoverecclesall.co.uk/zones.php?zone=4"' +
			'		alt="" />' +
			'	<area shape ="poly" coords ="260,236,270,236,300,262,292,276,358,340,204,340,204,286,240,272"' +
			'		href ="http://www.discoverecclesall.co.uk/zones.php?zone=5"' +
			'		alt="" />' +
			'	<area shape ="poly" coords ="136,236,145,237,166,273,200,286,200,340,80,340,80,286,118,272"' +
			'		href ="http://www.discoverecclesall.co.uk/zones.php?zone=6"' +
			'		alt="" />' +
			'</map>' ;

			// calculate left for popup based on interior dimension of viewport
			var w = (isIE)?document.documentElement.clientWidth:window.innerWidth;
			// left = (window.width - div.width - div.border-width*2)/2 - 15? (but not less than 0)
			// the additional 15px reduction accounts for the scroll-bar in FF only
			var l = '' + Math.max(0, Math.floor(w - 966 - 6)/2 - ((isIE)?0:15));
			// creation parameters are: popupDivId, content, width, height, left, top, hasCloser
//			pdm.createPopup('bigMap', '<img src="images/recompile/map/full_map.jpg" width="950" height="409" />', '966', '420', l, '250', true);
			pdm.createPopup('bigMap', content, '966', '420', l, '250', true);
			pdm.showPopup('bigMap');
			// NOTE: since hasCloser is true, the control for hiding the popup is 
			// embedded in the popup itself - no other means to close is provided
		}
		
		
		// declare global to page, so closer [x] can reference by name - set to null, 
		// so that popBigImg() can detect the state that there is not yet a popup 
		// manager for display of big images - same for StringUtil needed by popBigImg()
		var pdmGal = null;
		var strUtil = null;
		// manage popup div for display of big images in the context of the gallery.php
		// this approach minimizes resource demands and offers better user experience by 
		// providing only those image actually requested...avoids load delays and bandwidth
		// charges for those images not needed
		function popBigImg(aRef) {
			// {aRef} is a reference to the anchor element that fired the onclick event being 
			// handled by the current call to this function
			var isIE = -1 != navigator.userAgent.indexOf('MSIE');
			// private function to identify current top of page with respect to viewport
			function getVerticalScrollHeight() {
			   // Return vertical scroll height.
			   var vScroll;	// Initialize here to give function-global scope.
			   if (isIE) vScroll = document.documentElement.scrollTop;
			   else vScroll = window.pageYOffset;
			   return vScroll;
			}
			// private function to identify current top placement on page of top of popup with 
			// respect to viewport to center popup vertically
			function getTopForCenter(ih) {
				var vh = (isIE)?document.documentElement.clientHeight:window.innerHeight;
				return Math.floor((vh-ih)/2);
			}
			// if an instance of the StringUtil object hasn't been defined, do so now - name is 
			// in page global scope - only create once to enhance performance
			if (null == strUtil) strUtil = new aryooeye.StringUtil();
			// if the page global manager object doesn't yet exist, create and initialize the instance
			if (null == pdmGal) {
				pdmGal = new aryooeye.PopupDivManager();
				// extend base prototype to handle page mask
				pdmGal.doMask = function(onOff) {
					var el = document.getElementById('pageMask');
					el.style.height = '100%'
					el.style.width = '100%';
					el.style.display = ('on' == onOff)?'block':'none';
				}
				// override base prototype functions for hide and show to add mask handling
				pdmGal.hidePopup = function(puid) {
					try {
						document.getElementById(puid).style.display = 'none';
						this.doMask('off');
						return true;
					}
					catch (e) {	
						return false;
					}
				}
				pdmGal.showPopup = function(puid) {
					try {
						document.getElementById(puid).style.display = 'block';
						this.doMask('on');
						return true;
					}
					catch (e) {	
						return false;
					}
				}
				pdmGal.setName('pdmGal');	// since it's not the default name, update the object
				// reset border attributes from defaults before creating popup
				pdmGal.setBorderColor('#B0B');
				pdmGal.setBorderWidth('3px');
			}
			// immediately mask page to let user know something's going on
			pdmGal.doMask('on');
			// href of the anchor is actually the relative path to the file - this usage allows 
			// failures of the onclick JavaScript call to do the default anchor behavior of loading 
			// the big image to the browser - full onclick handler in page includes a "return false" 
			// statement that will defuse the href action, if the onclick is activated successfully
			var imgSrc = aRef.href;
			// compose id attribute for this image's div - div may or may not yet exist; id is 
			// composed as string "imgId_" prepedended to anchor's title with blanks removed
			var imgId = 'imgId_' + strUtil.dAN(aRef.title, ' ,&\'-&%#@!*^?\"');
			// if a div doesn't yet exist with the given id, then that container needs to
			// be created, attached to the page, and registered to the popup div manager for 
			// possible later reuse - creation overhead is a one-time charge, i.e., if visitor 
			// re-requests image, the popup manager simply redisplays the existing div element
			if (null == document.getElementById(imgId)) {
				var bigImg = new Image();
// TODO: revise determination of height and width of large image to allow variations - requires that 
//       process awaits complete load of image in order to assay actual values
//var imgLoaded = false;
//bigImg.onload = function() {imgLoaded = true;}
				bigImg.src = imgSrc;		// load requested image
//var cnt = 0;
//while (!imgLoaded && cnt < 100000) {
//	if (null == document.getElementById('pdmGalLoadMsg')) 
//		pdmGal.createPopup('pdmGalLoadMsg', 'loading image...please wait', 200, 30, 100, 100, false);
//	else pdmGal.showPopup('pdmGalLoadMsg');
//	cnt++;
//}
//pdmGal.hidePopup('pdmGalLoadMsg');
//alert(bigImg.height + ':' + bigImg.width);
				var ih = 300; // presumes all are 300px tall
				var iw = 400; // presumes all are 400px wide
				var cnt = 0;
				var title = aRef.title;	// will be used for both title and alt attributes of image
				var content = '<img src ="' + bigImg.src  + '" width ="' + iw + '" height ="' + ih + 
					'" alt="' + title + '" title="' + title + '" border="0" />';
				// calculate left for popup based on interior dimension of viewport
				var w = (isIE)?document.documentElement.clientWidth:window.innerWidth;
				// left = (window.width - div.width - div.border-width*2)/2 - 15? (but not less than 0)
				// the additional 15px reduction accounts for the scroll-bar in FF only
				var l = '' + Math.max(0, Math.floor(w - iw - 6)/2 - ((isIE)?0:15));
				// create non-default styles for the closer {x} subdiv on the popup - has to be done 
				// prior to creation of each new div in order to ensure that the closer [x] is 
				// properly placed for each div (widths could vary per images' width properties)
				var cStyle = '' +
					'background-color: white; ' +
					'border: 2px solid #B0B; ' +
					'color:  #B0B; ' +
					'cursor:pointer; ' +
					'font-family: Arial, sans-serif; ' +
					'font-size: 10px; ' +
					'font-weight: bold; ' +
					// set left to 4px beyond right-hand edge of image
					'left: ' + (iw + 8)  + 'px; ' +
					'margin: 2px; ' +
					// padding is 1px -left for IE, 1px -right for non-IE...go figure!
					'padding:' + ((isIE)?'0 0 0 1px':'0 1px 0 0') + '; ' +
					'position: absolute; ' +
					'top: 2px; ' +
					'text-align: center; ' +
					'width: 10px; ' +
					'top: 2px;' ;
				pdmGal.setCloserStyle(cStyle);
				// creation parameters are: popupDivId, content, width, height, left, top, hasCloser
				// width is that of image plus 10px for width of closer and 4px on either side of closer
				// private function to identify current top of page with respect to viewport
				function getVerticalScrollHeight() {
				   // Return vertical scroll height.
				   var vScroll;	// Initialize here to give function-global scope.
				   if (isIE) vScroll = document.documentElement.scrollTop;
				   else vScroll = window.pageYOffset;
				   return vScroll;
				}
				// private function to identify current top placement on page of top of popup with 
				// respect to viewport to center popup vertically
				function getTopForCenter(ih) {
					var vh = (isIE)?document.documentElement.clientHeight:window.innerHeight;
					return Math.floor((vh-ih)/2);
				}
				
				var oTop = getVerticalScrollHeight() + getTopForCenter(ih);
				pdmGal.createPopup(imgId, content, iw + 16, ih, l, oTop, true);
			}
			// if any other big image is open, close it before display next one
			pdmGal.hideAllPopups();
			// redo top and left to ensure that resize of the viewport doesn't put previously
			// registerd popups at their original, now wrong, positions
			document.getElementById(imgId).style.top = (getVerticalScrollHeight() + getTopForCenter(ih)) + 'px'; 
			var w = (isIE)?document.documentElement.clientWidth:window.innerWidth;
			var iw = 400; // presumes all are 400px wide
			document.getElementById(imgId).style.left = '' + 
				Math.max(0, Math.floor(w - iw - 6)/2 - ((isIE)?0:15)) +'px';
			// whether just now (above block) or previously created, display the popup
			pdmGal.showPopup(imgId);
			// NOTE: since hasCloser is true, the control for hiding the popup is 
			// embedded in the popup itself - no other means to close is provided
		}

