/****************************************************************************
*
* Copyright 2007 dynamIt Technologies, LLC.
*
* The following code is for the exclusive use of dynamIt Technologies, LLC.
* Any use of this code with written permission from dynamIt is prohibited.
*
* Report an abuse of this copyright to
*	dynamIt Technologies, LLC
*	4612 Sawmill Road
*	Columbus, Ohio 43220 USA
*	+1.614.538.0095
*
****************************************************************************/

/**************************************
* Some basic browser detection
**************************************/
var IE7 = false;
var IE6 = false;
var FF = false;
if (window.XMLHttpRequest) {
	if(document.epando){
		//IE7
		IE7 = true;
	}else{
		//mozilla, safari, opera, etc
		FF = true;
	}
} else {
	// IE6, older browsers
         IE6 = true;
}
/**************************************
* FIX IE 6 bug
**************************************/
var dialogOpen = false;
var dialogScroll = 0;
window.onscroll = function() {

        if(IE6) {
                if(dialogOpen) {
                        window.self.scrollTo(0, dialogScroll);
                }
        }

}

function scrollY() {

        var scroll = 0;
        if(document.body.scrollTop) scroll = document.body.scrollTop;
        else if(document.documentElement.scrollTop) scroll = document.documentElement.scrollTop;
        else if(window.pageYOffset) scroll = window.pageYOffset;

        return scroll;
}




/**************************************
* This method will initialize the dynamIt Ajax
* system by placing the
**************************************/
window.onload = dynamItInit;
var documentLoaded = false;
function dynamItInit() {
	var pos = (IE6) ? "absolute" : "fixed";

	var ca = document.createElement("div");
	var pu = document.createElement("div");
	var sl = document.createElement("div");
	ca.className = "coverAll";
	ca.setAttribute("id", "coverAll");
	ca.style.cssText = "position: " + pos + "; width: 1px; height: 1px; top: 0px; left: 0px; background-color: #000000; visibility: hidden; z-index: 1000; opacity: .60; filter: alpha(opacity=60);";
	pu.className = "popUpWin";
	pu.setAttribute("id", "popUpWin");
	pu.style.cssText = "position: " + pos + "; width: 1px; background-color: white; border: 1px solid black; font-size: 14px; font-weight:bold; visibility: hidden; z-index: 1001; padding: 0px;";
	sl.className = "simpleLoading";
	sl.setAttribute("id", "simpleLoading");
	sl.style.cssText = "color: #cc0000; font-size: 11px; font-weight: bold; background-color: white; border: 1px solid black; padding: 8px; position: absolute; visibility: hidden; opacity: .80; filter: alpha(opacity=80);";

	var body = document.body;
	body.insertBefore(ca, body.firstChild);
	body.insertBefore(pu, ca);
	body.insertBefore(sl, pu);
	
	documentLoaded = true;
}


/**************************************
* This method and variables will allow for
* the capturing of the mouse position at any time
**************************************/
document.onmousemove = dynamItMouse;

var xmouse = 0;
var ymouse = 0;
function dynamItMouse(e) {
	if (!e) var e = window.event;
	if (e.pageX || e.pageY) 	{
		xmouse = e.pageX;
		ymouse = e.pageY;
	}
	else if (e.clientX || e.clientY) 	{
		xmouse = e.clientX;
		ymouse = e.clientY;
            
        if (document.body) {
            xmouse += document.body.scrollLeft;
            ymouse += document.body.scrollTop;
        }
        if (document.documentElement) {
            xmouse += document.documentElement.scrollLeft;
            ymouse += document.documentElement.scrollTop;
        }
	}
}

/**************************************
* This method and variables will allow for
* the capturing of the current window size.
**************************************/
var windowWidth;
var windowHeight;
function getWindowSize() {
	if( typeof(window.innerWidth) == 'number' ) {
		windowWidth = window.innerWidth;
		windowHeight = window.innerHeight;
	} else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
		windowWidth = document.documentElement.clientWidth;
		windowHeight = document.documentElement.clientHeight;
	} else if ( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
		windowWidth = document.body.clientWidth;
		windowHeight = document.body.clientHeight;
	} else {
		windowWidth = screen.width;
		windowHeight = screen.height;
	}
}


/**************************************
* This method creates the object necessary to carry
* out an ajax request. This function will be used by
* the sendRequest and postRequest functions.
**************************************/
function GetXmlHttpObject(handler) {
	var objXMLHttp = null;

	if(window.XMLHttpRequest) {
		objXMLHttp = new XMLHttpRequest();
	} else if(window.ActiveXObject) {
		objXMLHttp = new ActiveXObject("Microsoft.XMLHTTP");
	}

	return objXMLHttp;
}


/**************************************
* This method will generate the necessary object
* and carry out the AJAX request via GET.
* url - the script url to execute.
* loadfcn - the function to be called on state change.
**************************************/
function sendRequest(url, loadfcn) {
	xmlHttp = GetXmlHttpObject();
	if(xmlHttp == null) {
		alert ("Browser does not support HTTP Request");
		return;
	}

	xmlHttp.onreadystatechange = loadfcn;
	xmlHttp.open("GET",url,true);
	xmlHttp.send(null);
}


/**************************************
* This method will generate the necessary object
* and carry out the AJAX request via POST.
* url - the script url to execute.
* data -  the url excoded data to send.
* loadfcn - the function to be called on state change.
**************************************/
function postRequest(url, data, loadfcn) {
	xmlHttp = GetXmlHttpObject();
	if(xmlHttp == null) {
		alert ("Browser does not support HTTP Request");
		return;
	}

	xmlHttp.onreadystatechange = loadfcn;
	xmlHttp.open("POST", url, true);
	xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
	xmlHttp.send(data);
}

/**************************************
* This method will parse all <script>
* tags on an ajax request and evaluate
* them.
**************************************/
function evalScriptTags(dom) {
	var scriptTags = dom.getElementsByTagName("SCRIPT");
    for( i=0; i<scriptTags.length; i++ ) {
		var script = scriptTags[i];
		eval(script.innerHTML);
	}
}


/**************************************
* This method takes in a reference to an html element
* and returns the element obj. If the parameter passed
* is the object it self, it will simply return it back
* to the caller. Otherwise, this function will attempt
* to retrieve the element by ID. Thus, this method also
* serves as an alias for document.getElementById().
**************************************/
function dynamItElem(obj) {
	try {
		if(typeof(obj) == 'object')
			return obj;
		else
			return document.getElementById(obj);
	}
	catch(e) {
		return null;
	}
}


/************************************
* The following methods deal with showing and hiding
* elements on the page.
************************************/
function dynamItShowMe(objId) {
	dynamItElem(objId).style.display = 'block';
}

function dynamItHideMe(objId) {
	dynamItElem(objId).style.display = 'none';
}

function dynamItToggleMe(objId) {
	if(dynamItElem(objId).style.display == 'none') {
		dynamItShowMe(objId);
	} else {
		dynamItHideMe(objId);
	}
}


/************************************
* The following methods deal with the dynamIt AJAX
* dialog box.
************************************/
function openDialog(html, w, h) {
    if(IE6) {
        hideSelects();
        dialogScroll = scrollY();
    }

    dialogOpen = true;

	var cover = dynamItElem('coverAll');
	cover.style.visibility = 'visible';

	var box = dynamItElem('popUpWin');
	box.style.visibility = 'visible';
	positionDialog(w, h);
	box.innerHTML = html;

	evalScriptTags(box);
}


function showSelects() {
    for(var i = 0; i < mySelects.length; i++) {
        mySelects[i].style.visibility = "visible";
    }
}

var mySelects;

function hideSelects() {
    mySelects = new Array();
    var sels = document.getElementsByTagName('select');
    for(var i = 0; i < sels.length; i++) {
        sels[i].style.visibility = "hidden";
        mySelects[mySelects.length] = sels[i];
    }
}

function positionDialog(w, h) {

    var cover = dynamItElem('coverAll');
	var box = dynamItElem('popUpWin');

	w = parseInt(w, 10);
	h = parseInt(h, 10);
	if(isNaN(w) || w == 0) w = 300;
	if(isNaN(h) || h == 0) h = 120;

	box.style.width = w + 'px';
	box.style.height = h + 'px';

	getWindowSize();

     var left = (windowWidth/2) - (w/2);
     var top = (windowHeight/2) - (h/2);

        if(IE6) {
                top  = top + dialogScroll;
                cover.style.top = dialogScroll + 'px';
        }

	box.style.left = left + 'px';
	box.style.top = top + 'px';

	cover.style.width = '100%';
	cover.style.height = '100%';

	if(IE6) {
		cover.style.height = windowHeight + 'px';
	}


}

function waitDialog(message) {
	var w = 300;
	var h = 125;
	var html = '';
	html += '<div>';
	html += '	<div id="dialogHeader">';
	html += '		Please wait.';
	html += '	</div>';
	html += '	<div id="dialogContent" align="center">';
	html += '		<div style="text-align:center; color:#555555">' + message + '</div>';
	html += '	</div>';
	html += '</div>';

	openDialog(html, w, h);

}

function confDialog(message) {
	var html = '';
	html += '<div>&nbsp;</div>';
	html += '<div style="text-align:center">' + message + '</div>';
	html += '<div>&nbsp;</div>';
    html += '<div style="text-align:center"><input type="button" value="   Ok   " onclick="closeDialog();" /></div>';

	var box = dynamItElem('popUpWin');
	box.innerHTML = html;
}

function closeDialog(reload_parent) {
	// We must hide the box and the cover,
	// but also shrink them, otherwise, cursor
	// will not appear in text boxes in Firefox

	var box = dynamItElem('popUpWin');
	box.style.visibility = 'hidden';
	box.style.width = '1px';
	box.style.height = '1px';
	box.style.top = '1px';
	box.style.left = '1px';

	// Ensure contents are cleared out
	// preventing old code from tricking
	// dynamItElem calls
	box.innerHTML = '';

	var cover = dynamItElem('coverAll');
	cover.style.visibility = 'hidden';
	cover.style.width = '1px';
	cover.style.height = '1px';

	// Reset scrolling behaviour
	box.style.overflow='hidden';
	box.style.overflowX='hidden';
	box.style.overflowY='hidden';


	if(IE6) showSelects();
	dialogOpen = false;

	if (true===reload_parent) top.parent.location.reload();
}


/**************************************
* Same as above however this was created
* to workaround a weird "closeDialog is not a function"
* error which occurred on some coppermine pages?
**************************************/
function closeDialogEx(reload_parent) {
	closeDialog(reload_parent);
}

/**************************************
* These methods will open up a very simple loading
* box at the mouse position and then close it again
* when done.
**************************************/
function openSimpleLoading() {
	var loadBox = dynamItElem('simpleLoading');
	loadBox.style.visibility = 'visible';
	loadBox.style.left = xmouse + 'px';
	loadBox.style.top = ymouse + 'px';
}

function closeSimpleLoading() {
	var loadBox = dynamItElem('simpleLoading');
	loadBox.style.visibility = 'hidden';
}


/**************************************
* This method given a url will use AJAX to retrieve
* the output at that URL and load them into the
* specificed HTML element
**************************************/
function dynamItLoad(url, pane) {

	var container = dynamItElem(pane);

	sendRequest(url, function() {
		if(isAjaxComplete(xmlHttp)) {
			if(container) {
				container.innerHTML = xmlHttp.responseText;
				evalScriptTags(container);
			}
			else {
				openDialog(xmlHttp.responseText);
			}
		}
	});
}

/**************************************
* This method given a url will use AJAX to retrieve
* the output at that URL and load them into the
* specificed HTML element
*
* onComplete parameter added 2007-09-05. This is a snippet
* of javascript code that will be executed upon
* completion of the loading.
**************************************/
function dynamItLoadEx(url, pane, w, h, onComplete) {

	var container = dynamItElem(pane);

	if(container) {
        openSimpleLoading();
	} else {
		openDialog('');
		waitDialog('Loading...Please wait.');
	}

	sendRequest(url, function() {
		if(isAjaxComplete(xmlHttp)) {
			if(container) {
				closeSimpleLoading();
				container.innerHTML = xmlHttp.responseText;
				evalScriptTags(container);
			} else {
				openDialog(xmlHttp.responseText, w, h);
			}

			if(onComplete.length) { eval(onComplete); }
		}
	});

}


/**************************************
* This method given a url will use AJAX to retrieve
* the output at that URL and load them into the
* specificed HTML element
**************************************/
function dynamItLoadDialog(action, width, height, scroll) {
	// Convert action to the correct URL
	var url = "index.php?dynamItAction="+action;

	dynamItLoadDialogEx(url, width, height, scroll);
}

/**************************************
* This method given a url will use AJAX to retrieve
* the output at that URL and load them into the
* specificed HTML element
**************************************/
function dynamItLoadDialogEx(url, width, height, scroll) {
	var scroll = safeBoolean(scroll);
	var win    = dynamItElem('popUpWin');

	// Open or simply reposition an existing dialog
	if ( to_lower(win.style.visibility) != 'visible' ) {
		openDialog("", width, height);
	} else {
		// Reposition Dialog
		if ( null != width && null != height ) positionDialog(width, height);
	}

	// Always :)
	win.style.padding='0px';

	// Configure scrolling behaviour
	win.style.overflow=scroll?'auto':'hidden';
	win.style.overflowX='hidden';
	win.style.overflowY=scroll?'scroll':'hidden';

	// Get loaded!
	dynamItLoad(url, win);
}

/**************************************
* This method take as its parameter and ordinary
* HTML form object and submits it via AJAX
* The script run by the ajax needs to echo
* back a javascript function call and nothing else.
**************************************/
function dynamItPublish(f) {
	var url = f.action;
	var pageData = dynamItFormData(f);

	if (f.method.toUpperCase() == "POST") {
		postRequest(url, pageData, function () {
			if(isAjaxComplete(xmlHttp)) {
				setTimeout(xmlHttp.responseText, 1);
			}
		});
	} else {
		url = url + "?" + pageData;
		sendRequest(url, function () {
			if(isAjaxComplete(xmlHttp)) {
				setTimeout(xmlHttp.responseText, 1);
			}
		});
	}
	return false;
}

/**************************************
* This method take as its parameter and ordinary
* HTML form object and submits it via AJAX
* The script run by the ajax needs to echo
* back a javascript function call and nothing else.
**************************************/
function dynamItPublishWait(f, waitmsg) {
	var url = f.action;
    var method = f.method;
	var pageData = dynamItFormData(f);

    waitDialog(waitmsg);
    
	if (method.toUpperCase() == "POST") {
		postRequest(url, pageData, function () {
			if(isAjaxComplete(xmlHttp)) {
				setTimeout(xmlHttp.responseText, 1);
			}
		});
	} else {
		url = url + "?" + pageData;
		sendRequest(url, function () {
			if(isAjaxComplete(xmlHttp)) {
				setTimeout(xmlHttp.responseText, 1);
			}
		});
	}
	return false;
}

/**************************************
* This method will turn an ordinary form into
* query string data.
**************************************/
function dynamItFormData(f) {
	var e;
	var data = new Array;
	for (var j = 0; j < f.elements.length; j++) {
		e = f.elements[j];
		if (e && e.name && e.name.length) {
			if(e.type == "radio" || e.type == "checkbox") {
				if(!e.checked) continue;
			}

			data.push(e.name + "=" + urlencode(e.value));
		}
	}

	return data.join("&");
}

/**************************************
* These methods aid in dynamically adding and
* removing HTML elements from the page.
**************************************/
function addDiv(conatiner, id, classname, inner) {
	var e = document.createElement('div');

	e.setAttribute('id', id);
	e.className = classname;
	e.innerHTML = inner;

	container.appendChild(e);
}

function remDiv(id) {
	var o = dynamItElem(id);

	var p = o.parentNode;
	p.removeChild(o);
}

function moveDiv(divId, newCont) {
    var d = dynamItElem(newCont);
    var o = dynamItElem(divId);
    var oldCont = o.parentNode;
    var o = oldCont.removeChild(o);
    d.appendChild(o);
}

/**************************************
* Returns true if AJAX request has
* completed.
**************************************/
function isAjaxComplete(xmlHttp) {
	return (xmlHttp.readyState == 4 || xmlHttp.readyState == "complete");
}

/**************************************
* PHP functions you know and love implemeneted
* in JavaScript.
**************************************/
function str_replace(find, replace, search) {
	return search.split(find).join(replace);
}

function urlencode(str) {
	return encodeURIComponent(str);
}


function substr(string, start, length) {
	var l = parseInt(length);
	if(isNaN(l)) {
		return string.substring(start);
	} else {
		return string.substring(start, start + length);
	}
}

function trim(str) {
	return str.replace(/^\s+|\s+$/g,"");
}

function ltrim(str) {
	return str.replace(/^\s+/,"");
}
function rtrim(str) {
	return this.replace(/\s+$/,"");
}

function empty(o) {
	if ((null==o) || (undefined==o)) {
		return true;
	} else if (typeof(o)=='string') {
		return trim(o).length<=0;
	}
	return false;
}

function safeBoolean(b) {
	return empty(b)?false:b;
}

/**************************************
* Dropdown of countries
**************************************/
function countries(fldname, width) {
	// select your default country from the following
	var aus = ''; // Australia - selected as default
	var can = '';                    // Canada
	var fra = '';                    // France
	var ger = '';                    // Germany
	var nz = '';                     // New Zealand
	var uk = '';                     // United Kingdom
	var us = 'selected="selected"';  // United States
	var xx = '';                     // add null entry and select as default

	// drop down country selection list
	// 233 countries with your choice of the above default country selections
	// copyright 11th December 2001, 29th December 2005 - Felgall Pty Ltd, Stephen Chapman
	// permission is granted to use this selection box script with your web page
	// provided that all of the code below and these comments
	// (including the copyright notice) are left intact
	document.writeln('<!-- start of drop down country selection list -->');
	document.writeln('<select name="' + fldname + '" id="' + fldname + '"style="width:' + width + 'px;" size="1">');
	if (xx != '') document.writeln('<option selected="selected"> </option>');
	document.writeln('<option>Afghanistan</option><option>&Aring;land Islands</option><option>Albania</option><option>Algeria</option><option>American Samoa</option><option>Andorra</option><option>Angola</option><option>Anguilla</option><option>Antarctica</option><option>Antigua and Barbuda</option><option>Argentina</option><option>Armenia</option><option>Aruba</option><option ' + aus + '>Australia</option><option>Austria</option><option>Azerbaijan</option><option>Bahamas</option><option>Bahrain</option><option>Bangladesh</option><option>Barbados</option><option>Belarus</option><option>Belgium</option><option>Belize</option><option>Benin</option><option>Bermuda</option><option>Bhutan</option><option>Bolivia</option><option>Bosnia and Herzegovina</option><option>Botswana</option>');
	document.writeln('<option>Bouvet Island</option><option>Brazil</option><option>British Indian Ocean territory</option><option>Brunei Darussalam</option><option>Bulgaria</option><option>Burkina Faso</option><option>Burundi</option><option>Cambodia</option><option>Cameroon</option><option' + can + '>Canada</option><option>Cape Verde</option><option>Cayman Islands</option><option>Central African Republic</option><option>Chad</option><option>Chile</option><option>China</option><option>Christmas Island</option><option>Cocos (Keeling) Islands</option><option>Colombia</option><option>Comoros</option><option>Congo</option><option>Congo, Democratic Republic</option><option>Cook Islands</option><option>Costa Rica</option><option>C&ocirc;te d\'Ivoire (Ivory Coast)</option><option>Croatia (Hrvatska)</option><option>Cuba</option><option>Cyprus</option>');
	document.writeln('<option>Czech Republic</option><option>Denmark</option><option>Djibouti</option><option>Dominica</option><option>Dominican Republic</option><option>East Timor</option><option>Ecuador</option><option>Egypt</option><option>El Salvador</option><option>Equatorial Guinea</option><option>Eritrea</option><option>Estonia</option><option>Ethiopia</option><option>Falkland Islands</option><option>Faroe Islands</option><option>Fiji</option><option>Finland</option><option ' + fra + '>France</option><option>French Guiana</option><option>French Polynesia</option><option>French Southern Territories</option><option>Gabon</option><option>Gambia</option><option>Georgia</option><option ' + ger + '>Germany</option><option>Ghana</option><option>Gibraltar</option><option>Greece</option><option>Greenland</option>');
	document.writeln('<option>Grenada</option><option>Guadeloupe</option><option>Guam</option><option>Guatemala</option><option>Guinea</option><option>Guinea-Bissau</option><option>Guyana</option><option>Haiti</option><option>Heard and McDonald Islands</option><option>Honduras</option><option>Hong Kong</option><option>Hungary</option><option>Iceland</option><option>India</option><option>Indonesia</option><!-- copyright Felgall Pty Ltd --><option>Iran</option><option>Iraq</option><option>Ireland</option><option>Israel</option><option>Italy</option><option>Jamaica</option><option>Japan</option><option>Jordan</option><option>Kazakhstan</option><option>Kenya</option><option>Kiribati</option><option>Korea (north)</option><option>Korea (south)</option><option>Kuwait</option><option>Kyrgyzstan</option>');
	document.writeln('<option>Lao People\'s Democratic Republic</option><option>Latvia</option><option>Lebanon</option><option>Lesotho</option><option>Liberia</option><option>Libyan Arab Jamahiriya</option><option>Liechtenstein</option><option>Lithuania</option><option>Luxembourg</option><option>Macao</option><option>Macedonia</option><option>Madagascar</option><option>Malawi</option><option>Malaysia</option><option>Maldives</option><option>Mali</option><option>Malta</option><option>Marshall Islands</option><option>Martinique</option><option>Mauritania</option><option>Mauritius</option><option>Mayotte</option><option>Mexico</option><option>Micronesia</option><option>Moldova</option><option>Monaco</option><option>Mongolia</option><option>Montserrat</option><option>Morocco</option><option>Mozambique</option><option>Myanmar</option><option>Namibia</option>');
	document.writeln('<option>Nauru</option><option>Nepal</option><option>Netherlands</option><option>Netherlands Antilles</option><option>New Caledonia</option><option ' + nz + '>New Zealand</option><option>Nicaragua</option><option>Niger</option><option>Nigeria</option><option>Niue</option><option>Norfolk Island</option><option>Northern Mariana Islands</option><option>Norway</option><option>Oman</option><option>Pakistan</option><option>Palau</option><option>Palestinian Territories</option><option>Panama</option><option>Papua New Guinea</option><option>Paraguay</option><option>Peru</option><option>Philippines</option><option>Pitcairn</option><option>Poland</option><option>Portugal</option><option>Puerto Rico</option><option>Qatar</option><option>R&eacute;union</option><option>Romania</option><option>Russian Federation</option>');
	document.writeln('<option>Rwanda</option><option>Saint Helena</option><option>Saint Kitts and Nevis</option><option>Saint Lucia</option><option>Saint Pierre and Miquelon</option><option>Saint Vincent and the Grenadines</option><option>Samoa</option><option>San Marino</option><option>Sao Tome and Principe</option><!-- copyright Felgall Pty Ltd --><option>Saudi Arabia</option><option>Senegal</option><option>Serbia and Montenegro</option><option>Seychelles</option><option>Sierra Leone</option><option>Singapore</option><option>Slovakia</option><option>Slovenia</option><option>Solomon Islands</option><option>Somalia</option><option>South Africa</option><option>South Georgia and the South Sandwich Islands</option><option>Spain</option><option>Sri Lanka</option><option>Sudan</option><option>Suriname</option>');
	document.writeln('<option>Svalbard and Jan Mayen Islands</option><option>Swaziland</option><option>Sweden</option><option>Switzerland</option><option>Syria</option><option>Taiwan</option><option>Tajikistan</option><option>Tanzania</option><option>Thailand</option><option>Togo</option><option>Tokelau</option><option>Tonga</option><option>Trinidad and Tobago</option><option>Tunisia</option><option>Turkey</option><option>Turkmenistan</option><option>Turks and Caicos Islands</option><option>Tuvalu</option><option>Uganda</option><option>Ukraine</option><option>United Arab Emirates</option><option ' + uk + '>United Kingdom</option><option ' + us + '>United States of America</option><option>Uruguay</option><option>Uzbekistan</option><option>Vanuatu</option><option>Vatican City</option>');
	document.writeln('<option>Venezuela</option><option>Vietnam</option><option>Virgin Islands (British)</option><option>Virgin Islands (US)</option><option>Wallis and Futuna Islands</option><option>Western Sahara</option><option>Yemen</option><option>Zaire</option><option>Zambia</option><option>Zimbabwe</option></select>');
	document.writeln('<!-- end of drop down country selection list -->');
}


/******************************************
 * DOM Traversal Helper Functions
 ******************************************/
function dom_prev(sib) {
	while ((sib = sib.previousSibling)) if (!is_ignorable(sib)) return sib;
	return null;
}
function dom_next(sib) {
	while ((sib = sib.nextSibling)) if (!is_ignorable(sib)) return sib;
	return null;
}
function dom_firstchild(par) {
	var res = par.firstChild;
	while(res) {
		if(!is_ignorable(res)) return res;
		res = res.nextSibling;
	}
	return null;
}
function dom_lastchild(par) {
	var res = par.lastChild;
	while(res) {
		if(!is_ignorable(res)) return res;
		res = res.previousSibling;
	}
	return null;
}
function is_all_ws(nod) { return !(/[^\t\n\r ]/.test(nod.data)); }
function is_ignorable(nod) { return (nod.nodeType == 8) || ((nod.nodeType == 3) && is_all_ws(nod)); }
function to_lower(str) { var x = String(str); return x.toLowerCase(); }
function to_upper(str) { var x = String(str); return x.toUpperCase(); }

/*******************************************
 * Call this function with an input_id
 * and a message (which may be null or '')
 * the code will then change the associated
 * <label> tag to include your message.
 * This is great to call from AJAX.
 *******************************************/
function dynamItValidationLabel( input_id, message ) {
	var i = dynamItElem(input_id);
	if ( null !== i ) {
		var j = dom_prev(i);
		if (null !== j && j.tagName == 'LABEL') {
			if ( empty(message) ) {
				j.innerHTML = j.innerHTML.replace(/<br.*$/i,"");
				j.style.color = ''; // Cross browser compatible - don't use removeProperty
			} else {
				j.style.color="red";
				j.innerHTML = j.innerHTML + "<br /><i style='font-size:80%;'>" + message + "</i>&nbsp;"
			}
		}
	}
}

/*******************************************
 * Call this function with an input_id
 * and a message (which may be null or '')
 * the code will then change the <div>
 * This will also clear all messages if
 * a wildcard is used, e.g. "error_row_*"
 *******************************************/
function dynamItValidationMessage( id, message ) {
	setTagsInnerHtml('div', id, empty(message)?'':message);
}

/*******************************************
 * Deligate for top.location, allows for
 * future functionality on a URL change.
 *******************************************/
function gotoUrl(url) {
	top.location=url;
	return false;
}

/*******************************************
 * Enable/Disable a form while processing
 * occurs. The message parameter displays
 * in the form's submit button. When it's
 * null or '' it will renable the form.
 *******************************************/
var enableFormMonitorArray = new Array();
function submitForm(formId, submitId, message, ajaxPublish) {
	var form 		= dynamItElem(formId);
	var disable	 	= !empty(message);

	if ( disable ) {
		// Remember state and change message
		submit = dynamItElem(submitId);
		if ( submit && !submit.disabled ) {
			enableFormMonitorArray[form.id]=new Array(submit, submit.value);
			submit.value = message;
			submit.disabled = true;
		}
	} else {
		// Restore form to normal state
		if ( enableFormMonitorArray[form.id] ) {
			submit 		 = enableFormMonitorArray[form.id][0];
			submit.value = enableFormMonitorArray[form.id][1];
			submit.disabled = false;
		}
	}

	// Reset validation messages
	for (var i = 0; i < form.elements.length; i++) {
		e = form.elements[i];
		if (e && e.name && e.name.length) {
			dynamItValidationLabel(e.id, null);
		}
	}

	// All done, ajax publish if requested
	if ( ajaxPublish ) {
		return dynamItPublish(form);
	} else {
		return true;
	}
}


/*******************************************
 * If the current select has "_addnew_" then
 * this function will reveal the subsequent
 * label and input field.
 * Optional additional arguments can be
 * supplied. These additional IDs will be
 * revealed also.
 *******************************************/
function formAddNewSelect(select) {
	var displayStyle 	  = (select.value == "_addnew_")?'inline':'none';
	var displayStylePrime = (select.value == "_addnew_")?'none':'inline';

	// Enable/disable the label and input immediately following this select
	var sibling = select;
	while( sibling=dom_next(sibling) ) {
		if ( sibling.id == "searchselect" ) {
			sibling.style.display=displayStylePrime;
			if ('BUTTON' == sibling.type) break;
		} else {
			sibling.style.display=displayStyle;
			if ('INPUT' == sibling.tagName) break;
		}
	}

	// Now process variable argument list, changing
	// the indicated control and the preceding label.
	for(var i=1; i<arguments.length; i++) {
    	sibling = dynamItElem(arguments[i]);			//Should this have "var"?
		if ( null != sibling ) {
			// Enable/disable control
			sibling.style.display = displayStyle;
			previous = dom_prev(sibling);
			// Now locate previous tag and change its display style if and only if its a lablel.
			if (null != previous && 'LABEL' == previous.tagName) previous.style.display = displayStyle;

			if ( 'SELECT'==sibling.tagName && 'none'==displayStyle ) {
				// This select may have its own call to this function.
				// We need to trigger it by changing the select to 'nothing'
				sibling.selectedIndex = 0;
				sibling.onchange();
			}

		}
	}
}

/*******************************************
 * Will search all tags (tag) with id (id)
 * and replace the innerHtml with html
 *******************************************/
function setTagsInnerHtml( tag, id, html ) {
	var allTags = document.body.getElementsByTagName(to_upper(tag));

	if (id.indexOf("*")>=0) {
		// Glob matching (synthesized)
		var pattern = id.replace('.', '\\.');
		pattern = pattern.replace('*', '(.*?)');

		for (var tg = 0; tg< allTags.length; tg++) {
			var tag = allTags[tg];
			if ( tag.id && null != (tag.id.match(pattern)) ) {
				tag.innerHTML = html;
			}
		}
	}
	else {
		// Regular match
		for (var tg = 0; tg< allTags.length; tg++) {
			var tag = allTags[tg];
			if ( tag.id && tag.id == id ) {
				tag.innerHTML = html;
			}
		}
	}
}



/***********************************************
 * This method acts much like the dynamItPublish
 * function but will visit a URL rather than
 * publish a form. Data sent using GET
 ***********************************************/
function dynamItSend(url) {
	sendRequest(url, function () {
		if(isAjaxComplete(xmlHttp)) {
			setTimeout(xmlHttp.responseText, 1);
		}
	});
}

/***********************************************
 * Produce a dialog box, OK / CANCEL
 * Will use AJAX to send the supplied URL
 ***********************************************/
 function dynamItSendOnConfirm(url, title, message) {
	url = str_replace('\'', '\\\'', url);

	_dynamItOnConfirm( '<input type="button" id="button" onclick="dynamItSend(\'' + url + '\');"  value="OK"> &nbsp; ',
					   title,
					   message
					 );
}

/***********************************************
 * Produce a dialog box, OK / CANCEL
 * Will use AJAX to send the supplied URL
 ***********************************************/
function dynamItSendOnConfirmWait(url, title, message) {
	url = str_replace('\'', '\\\'', url);

	_dynamItOnConfirm( '<input type="button" id="button" onclick="waitDialog(\'<br/><br/>Working...\');dynamItSend(\'' + url + '\');"  value="OK"> &nbsp; ',
					   title,
					   message
					 );
}

/***********************************************
 * Produce a dialog box, OK / CANCEL
 * Will change current webpage for url
 ***********************************************/
function dynamItFunctionOnConfirm(func, title, message) {
	func = str_replace('\'', '\\\'', func);
	_dynamItOnConfirm( '<input type="button" id="button" onclick="javascript:' + func + ';" value="OK"> &nbsp; ',
					   title,
					   message
					 );
}

/***********************************************
 * Produce a dialog box, OK / CANCEL
 * Will change current webpage for url
 ***********************************************/
function dynamItLinkOnConfirm(url, title, message) {
	url = str_replace('\'', '\\\'', url);
	_dynamItOnConfirm( '<input type="button" id="button" onclick="location.href=\'' + url + '\';" value="OK"> &nbsp; ',
					   title,
					   message
					 );
}

/***********************************************
 * Refactored internal function for Send/Link
 * OnConfirm
 ***********************************************/
 function _dynamItOnConfirm(htmlOK, title, message) {
	var html = '<div id="dialog300"><div id="dialogHeader">' + title + '</div>';
	html += '<div id="dialogContent" style="text-align:center;">' + message + '</div>';
	html += '<div>&nbsp;</div>';
	html += '<div style="text-align:center;">'
	html += htmlOK;
	html += '<input type="button" id="button" onclick="closeDialog();" value="CANCEL">';
	html += '</div></div>';

	openDialog(html);
}


/***********************************************
 * Alter a URL so that it reloads with a
 * different parameter.
 ***********************************************/
function dynamItChangeParam(param, newValue, url) {
	var newUrl 		 = String(url);
	var paramEq 	 = param+"=";
	var currentValue = dynamItGetParam(param, newUrl);

	if (""==currentValue) {
		// Always remove the #, that tends to mess things up when we append
		newUrl = newUrl.replace('#','');
		newUrl = newUrl + (newUrl.indexOf('?')>0?'&':'?') + paramEq + newValue;
	}
	else {
		newUrl = newUrl.replace(paramEq+currentValue,paramEq+newValue);
	}

	return newUrl;
}

/***********************************************
 * Fetch a single parameter
 ***********************************************/
function dynamItGetParam( name, url )
{
  var regex = new RegExp( "[\\?&]"+name+"=([^&#]*)" );
  var params = regex.exec( url );
  if( params == null )
    return "";
  else
    return params[1];
}



/**
 * A class to parse color values
 * @author Stoyan Stefanov <sstoo@gmail.com>
 * @link   http://www.phpied.com/rgb-color-parser-in-javascript/
 * @license Use it if you like it
 */
function RGBColor(color_string)
{
    this.ok = false;

    // strip any leading #
    if (color_string.charAt(0) == '#') { // remove # if any
        color_string = color_string.substr(1,6);
    }

    color_string = color_string.replace(/ /g,'');
    color_string = color_string.toLowerCase();

    // before getting into regexps, try simple matches
    // and overwrite the input
    var simple_colors = {
        aliceblue: 'f0f8ff',
        antiquewhite: 'faebd7',
        aqua: '00ffff',
        aquamarine: '7fffd4',
        azure: 'f0ffff',
        beige: 'f5f5dc',
        bisque: 'ffe4c4',
        black: '000000',
        blanchedalmond: 'ffebcd',
        blue: '0000ff',
        blueviolet: '8a2be2',
        brown: 'a52a2a',
        burlywood: 'deb887',
        cadetblue: '5f9ea0',
        chartreuse: '7fff00',
        chocolate: 'd2691e',
        coral: 'ff7f50',
        cornflowerblue: '6495ed',
        cornsilk: 'fff8dc',
        crimson: 'dc143c',
        cyan: '00ffff',
        darkblue: '00008b',
        darkcyan: '008b8b',
        darkgoldenrod: 'b8860b',
        darkgray: 'a9a9a9',
        darkgreen: '006400',
        darkkhaki: 'bdb76b',
        darkmagenta: '8b008b',
        darkolivegreen: '556b2f',
        darkorange: 'ff8c00',
        darkorchid: '9932cc',
        darkred: '8b0000',
        darksalmon: 'e9967a',
        darkseagreen: '8fbc8f',
        darkslateblue: '483d8b',
        darkslategray: '2f4f4f',
        darkturquoise: '00ced1',
        darkviolet: '9400d3',
        deeppink: 'ff1493',
        deepskyblue: '00bfff',
        dimgray: '696969',
        dodgerblue: '1e90ff',
        feldspar: 'd19275',
        firebrick: 'b22222',
        floralwhite: 'fffaf0',
        forestgreen: '228b22',
        fuchsia: 'ff00ff',
        gainsboro: 'dcdcdc',
        ghostwhite: 'f8f8ff',
        gold: 'ffd700',
        goldenrod: 'daa520',
        gray: '808080',
        green: '008000',
        greenyellow: 'adff2f',
        honeydew: 'f0fff0',
        hotpink: 'ff69b4',
        indianred : 'cd5c5c',
        indigo : '4b0082',
        ivory: 'fffff0',
        khaki: 'f0e68c',
        lavender: 'e6e6fa',
        lavenderblush: 'fff0f5',
        lawngreen: '7cfc00',
        lemonchiffon: 'fffacd',
        lightblue: 'add8e6',
        lightcoral: 'f08080',
        lightcyan: 'e0ffff',
        lightgoldenrodyellow: 'fafad2',
        lightgrey: 'd3d3d3',
        lightgreen: '90ee90',
        lightpink: 'ffb6c1',
        lightsalmon: 'ffa07a',
        lightseagreen: '20b2aa',
        lightskyblue: '87cefa',
        lightslateblue: '8470ff',
        lightslategray: '778899',
        lightsteelblue: 'b0c4de',
        lightyellow: 'ffffe0',
        lime: '00ff00',
        limegreen: '32cd32',
        linen: 'faf0e6',
        magenta: 'ff00ff',
        maroon: '800000',
        mediumaquamarine: '66cdaa',
        mediumblue: '0000cd',
        mediumorchid: 'ba55d3',
        mediumpurple: '9370d8',
        mediumseagreen: '3cb371',
        mediumslateblue: '7b68ee',
        mediumspringgreen: '00fa9a',
        mediumturquoise: '48d1cc',
        mediumvioletred: 'c71585',
        midnightblue: '191970',
        mintcream: 'f5fffa',
        mistyrose: 'ffe4e1',
        moccasin: 'ffe4b5',
        navajowhite: 'ffdead',
        navy: '000080',
        oldlace: 'fdf5e6',
        olive: '808000',
        olivedrab: '6b8e23',
        orange: 'ffa500',
        orangered: 'ff4500',
        orchid: 'da70d6',
        palegoldenrod: 'eee8aa',
        palegreen: '98fb98',
        paleturquoise: 'afeeee',
        palevioletred: 'd87093',
        papayawhip: 'ffefd5',
        peachpuff: 'ffdab9',
        peru: 'cd853f',
        pink: 'ffc0cb',
        plum: 'dda0dd',
        powderblue: 'b0e0e6',
        purple: '800080',
        red: 'ff0000',
        rosybrown: 'bc8f8f',
        royalblue: '4169e1',
        saddlebrown: '8b4513',
        salmon: 'fa8072',
        sandybrown: 'f4a460',
        seagreen: '2e8b57',
        seashell: 'fff5ee',
        sienna: 'a0522d',
        silver: 'c0c0c0',
        skyblue: '87ceeb',
        slateblue: '6a5acd',
        slategray: '708090',
        snow: 'fffafa',
        springgreen: '00ff7f',
        steelblue: '4682b4',
        tan: 'd2b48c',
        teal: '008080',
        thistle: 'd8bfd8',
        tomato: 'ff6347',
        turquoise: '40e0d0',
        violet: 'ee82ee',
        violetred: 'd02090',
        wheat: 'f5deb3',
        white: 'ffffff',
        whitesmoke: 'f5f5f5',
        yellow: 'ffff00',
        yellowgreen: '9acd32'
    };
    for (var key in simple_colors) {
        if (color_string == key) {
            color_string = simple_colors[key];
        }
    }
    // emd of simple type-in colors

    // array of color definition objects
    var color_defs = [
        {
            re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
            example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'],
            process: function (bits){
                return [
                    parseInt(bits[1]),
                    parseInt(bits[2]),
                    parseInt(bits[3])
                ];
            }
        },
        {
            re: /^(\w{2})(\w{2})(\w{2})$/,
            example: ['#00ff00', '336699'],
            process: function (bits){
                return [
                    parseInt(bits[1], 16),
                    parseInt(bits[2], 16),
                    parseInt(bits[3], 16)
                ];
            }
        },
        {
            re: /^(\w{1})(\w{1})(\w{1})$/,
            example: ['#fb0', 'f0f'],
            process: function (bits){
                return [
                    parseInt(bits[1] + bits[1], 16),
                    parseInt(bits[2] + bits[2], 16),
                    parseInt(bits[3] + bits[3], 16)
                ];
            }
        }
    ];

    // search through the definitions to find a match
    for (var i = 0; i < color_defs.length; i++) {
        var re = color_defs[i].re;
        var processor = color_defs[i].process;
        var bits = re.exec(color_string);
        if (bits) {
            channels = processor(bits);
            this.r = channels[0];
            this.g = channels[1];
            this.b = channels[2];
            this.ok = true;
        }

    }

    // validate/cleanup values
    this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r);
    this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g);
    this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b);

    // some getters
    this.toRGB = function () {
        return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')';
    }
    this.toHex = function () {
        var r = this.r.toString(16);
        var g = this.g.toString(16);
        var b = this.b.toString(16);
        if (r.length == 1) r = '0' + r;
        if (g.length == 1) g = '0' + g;
        if (b.length == 1) b = '0' + b;
        return '#' + r + g + b;
    }

    // help
    this.getHelpXML = function () {

        var examples = new Array();
        // add regexps
        for (var i = 0; i < color_defs.length; i++) {
            var example = color_defs[i].example;
            for (var j = 0; j < example.length; j++) {
                examples[examples.length] = example[j];
            }
        }
        // add type-in colors
        for (var sc in simple_colors) {
            examples[examples.length] = sc;
        }

        var xml = document.createElement('ul');
        xml.setAttribute('id', 'rgbcolor-examples');
        for (var i = 0; i < examples.length; i++) {
            try {
                var list_item = document.createElement('li');
                var list_color = new RGBColor(examples[i]);
                var example_div = document.createElement('div');
                example_div.style.cssText =
                        'margin: 3px; '
                        + 'border: 1px solid black; '
                        + 'background:' + list_color.toHex() + '; '
                        + 'color:' + list_color.toHex()
                ;
                example_div.appendChild(document.createTextNode('test'));
                var list_item_value = document.createTextNode(
                    ' ' + examples[i] + ' -> ' + list_color.toRGB() + ' -> ' + list_color.toHex()
                );
                list_item.appendChild(example_div);
                list_item.appendChild(list_item_value);
                xml.appendChild(list_item);

            } catch(e){}
        }
        return xml;

    }

}
