/*
* CATS
* JavaScript Library
*
* Portions Copyright (C) 2005 - 2007 Cognizo Technologies, Inc.
*
* EventCache Copyright (C) 2005 Mark Wubben with modifications made
* by Cognizo Technologies, Inc. EventCache is licensed under the CC-GNU
* LGPL .
*
* addEvent() Copyright (C) 2001 Scott Andrew LePera with modifications
* made by Cognizo Technologies, Inc. No license was given; however,
* modifications made by Cognizo Technologies, Inc. are subject to the
* terms of the CATS Public License Version 1.1 (see below).
* http://www.scottandrew.com/weblog/articles/cbs-events
*
* The contents of this file are subject to the CATS Public License
* Version 1.1a (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.catsone.com/.
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is "CATS Standard Edition".
*
* The Initial Developer of the Original Code is Cognizo Technologies, Inc.
* Portions created by the Initial Developer are Copyright (C) 2005 - 2007
* (or from the year in which this file was created to the year 2007) by
* Cognizo Technologies, Inc. All Rights Reserved.
*
*
* $Id: lib.js 3488 2007-11-08 02:19:17Z will $
*/
/* Data item type flags. These should match up with the flags
* from config.php.
*/
var DATA_ITEM_CANDIDATE = 100;
var DATA_ITEM_COMPANY = 200;
var DATA_ITEM_CONTACT = 300;
var DATA_ITEM_JOBORDER = 400;
/* Set by TemplateUtility drawing headers. */
var CATSIndexName;
/* Default timeout for AJAX requests; 15 seconds. */
var AJAX_TIMEOUT = 15000;
/**
* Returns true if the string is a valid positive integer.
*
* @return boolean
*/
function stringIsNumeric(string)
{
for (var i = 0; i < string.length; i++)
{
var character = string.charAt(i);
if ((character < '0') || (character > '9'))
{
return false;
}
}
return true;
}
/**
* Changes a parent document block's style attribute to make it hidden (by id).
*
* @return void
*/
function hideParentBlock(elementID)
{
element = parent.document.getElementById(elementID);
element.parentNode.removeChild(element);
}
/**
* Changes a parent document block's style attribute to make it hidden (by id).
*
* @return void
*/
function showParentBlock(elementID)
{
element = parent.document.getElementById(elementID);
element.parentNode.removeChild(element);
}
/**
* Opens a centered popup window.
*
* @return void
*/
function openCenteredPopup(url, name, width, height, scrollBars)
{
var optionString;
optionString = 'width=' + width + ',height=' + height;
optionString += ',top=' + ((screen.availHeight - height) / 2) + ',left=' + ((screen.availWidth - width) / 2);
optionString += ',scrollbars=';
optionString += (scrollBars ? 'yes' : 'no');
/* Open the new window. */
newWindow = window.open(url, name, optionString);
/* If this window (parent) has focus, give focus to the popup (child). */
if (window.focus)
{
newWindow.focus();
}
}
/**
* Redirects the browser to a url.
*
* @return void
*/
function goToURL(url)
{
window.location = url;
}
/**
* Redirects the browser to a url.
*
* @return void
*/
function parentGoToURL(url)
{
parent.window.location = url;
}
function parentHidePopWin()
{
parent.hidePopWin();
}
function parentHidePopWinRefresh()
{
parent.hidePopWinRefresh();
}
function parentSetPopTitle(title)
{
parent.setPopTitle(title);
}
/**
* Replaces HTML special characters in text to be output-safe.
*
* @param string text to escape
* @return string escaped text
*/
function escapeHTML(text)
{
text = text.replace('&', '&');
text = text.replace('<', '<');
text = text.replace('>', '>');
text = text.replace('"', '"');
text = text.replace("'", ''');
return text;
}
/**
* Replaces output-save HTML with real text characters.
*
* @param string text to unescape
* @return string escaped text
*/
function unEscapeHTML(text)
{
text = text.replace('&', '&');
text = text.replace('<', '<');
text = text.replace('>', '>');
text = text.replace('"', '"');
text = text.replace(''', "'");
return text;
}
/**
* Encodes text for transmission via HTTP.
*
* @param string text to encode
* @return string encoded text
*/
function urlEncode(text)
{
/* Force JavaScript to always treat 'text' as a string. */
text += '';
/* encodeURIComponent() doesn't handle the ' character. */
text = text.replace(/\'/g, '%27');
/* Don't use escape(), as it doesn't properly handle UTF-8. */
text = encodeURIComponent(text);
return text;
}
/**
* Acts the same as PHP's urldecode.
*
* @param string text to unescape
* @return string escaped text
*/
function urlDecode(text)
{
while (text.indexOf('+') != -1)
{
text = text.replace('+', '%20');
}
/* Don't use unescape(), as it doesn't properly handle UTF-8. */
text = decodeURIComponent(text);
return text;
}
/**
* Converts a JavaScript array to a seralize()-formatted PHP array in string
* format.
*
* PHP: $myArray = unserialize(urldecode($_POST['myArray']));
* Remember this is unsafe input and it should not be trusted!
*
* Pass this through urlEncode() (above) before adding to a request.
*/
function serializeArray(array)
{
var string = 'a:' + array.length + ':{';
for (var i = 0; i < array.length; ++i)
{
string += 'i:' + i + ';s:' + String(array[i]).length + ':"'
+ String(array[i]) + '";';
}
return string + '}';
}
/**
* Removes leading and trailing whitespace from text.
*
* @param string text to clean up
* @return string cleaned string
*/
function trim(text)
{
return text.replace(/^\s*|\s*$/g, '');
}
/**
* Gets an XMLHTTP / XMLHttpRequest object for AJAX use.
*
* @return void
*/
function AJAX_getXMLHttpObject()
{
/* Array of possible names for the Microsoft XMLHTTP ActiveX. */
var MSXML_XMLHTTP_PROGIDS = new Array(
'Microsoft.XMLHTTP',
'MSXML2.XMLHTTP',
'MSXML2.XMLHTTP.5.0',
'MSXML2.XMLHTTP.4.0',
'MSXML2.XMLHTTP.3.0'
);
var xmlHttp;
try
{
xmlHttp = new XMLHttpRequest();
}
catch (errorA)
{
var found = false;
/* Try to figure out what Microsoft might have called their ActiveX control. */
for (var i = 0; (i < MSXML_XMLHTTP_PROGIDS.length && !found); i++)
{
try
{
xmlHttp = new ActiveXObject(MSXML_XMLHTTP_PROGIDS[i]);
found = true;
}
catch (errorB)
{
}
}
if (!found)
{
return null;
}
}
return xmlHttp;
}
/**
* Sends HTTP content headers for an AJAX POST request.
*
* @return void
*/
function AJAX_sendPOSTHeaders(http, contentLength)
{
http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
http.setRequestHeader('Content-length', contentLength);
http.setRequestHeader('Connection', 'close');
}
/**
* Returns a random hash to append to an HTTP POST to keep data from being
* cached (URL-encoded).
*
* @return random POST variable hash
*/
function AJAX_getRandomPOSTHash()
{
return '&rhash=' + urlEncode(parseInt(Math.random() * 99999999).toString());
}
/**
* Returns a formatted session cookie to append to an HTTP POST.
*
* @return formatted cookie
*/
function AJAX_getPOSTSessionID(sessionCookie)
{
return '&' + sessionCookie;
}
/**
* Sends an AJAX HTTP POST request back to the specified URL.
*
* @return void
*/
function AJAX_POST(http, url, POSTData, callBack, timeout, sessionCookie,
silentTimeout)
{
/* Add a random hash to the POST data to keep IE from caching it. */
POSTData += AJAX_getRandomPOSTHash();
/* Append the session cookie if we're using secure AJAX. */
if (sessionCookie != null)
{
POSTData += AJAX_getPOSTSessionID(sessionCookie);
}
/* Uncomment for debugging. */
//alert(POSTData);
/* Open the socket and send POST headers. */
http.open('POST', url, true);
AJAX_sendPOSTHeaders(http, POSTData.length);
/* Callback function. */
http.onreadystatechange = callBack;
/* Send the data. */
http.send(POSTData);
/* Abort after timeout expires. */
if (timeout != 0)
{
var timeoutCallback = function()
{
if (!AJAX_isCallInProgress(http))
{
return;
}
http.abort();
if (!silentTimeout)
{
alert(
'Timeout on AJAX query after ' + (timeout / 1000) +
' seconds. Please refresh the page and try again.'
);
}
}
window.setTimeout(timeoutCallback, timeout);
}
}
/**
* Sends an AJAX HTTP POST request to the CATS AJAX Delegation Module.
*
* @return void
*/
function AJAX_callCATSFunction(http, funcName, POSTData, callBack,
extraTimeout, sessionCookie, silentTimeout, disableBuffering)
{
/* Prepend the function name to the postdata. */
var newPOSTData = 'f=' + funcName + POSTData;
if (disableBuffering)
{
newPOSTData += '&nobuffer=true';
}
AJAX_POST(
http,
'ajax.php',
newPOSTData,
callBack,
(AJAX_TIMEOUT + extraTimeout),
sessionCookie,
silentTimeout
);
}
/**
* Is an XMLHTTP object being used for an active call?
*
* @return boolean is object active
*/
function AJAX_isCallInProgress(http)
{
switch (http.readyState)
{
case 1:
case 2:
case 3:
return true;
break;
}
return false;
}
/**
* Is a PHP error message contained in responseText?
*
* @return boolean is PHP error
*/
function AJAX_isPHPError(responseText)
{
return (responseText.indexOf(' on line ') != -1);
}
/*
****************************************************************************
* Notes / Job Description Truncation
****************************************************************************
*/
showFullDescription = false;
showFullNotes = false;
function toggleDescription()
{
var shortNode = document.getElementById('shortDescription');
var fullNode = document.getElementById('fullDescription');
toggleNode(showFullDescription, shortNode, fullNode);
if (showFullDescription == true)
{
showFullDescription = false;
}
else
{
showFullDescription = true;
}
}
function toggleNotes()
{
var shortNode = document.getElementById('shortNotes');
var fullNode = document.getElementById('fullNotes');
toggleNode(showFullNotes, shortNode, fullNode);
if (showFullNotes == true)
{
showFullNotes = false;
}
else
{
showFullNotes = true;
}
}
function toggleNode(showFull, shortNode, fullNode)
{
if (showFull == true)
{
shortNode.style.display = 'block';
fullNode.style.display = 'none';
}
else
{
shortNode.style.display = 'none';
fullNode.style.display = 'block';
}
}
/**
* Populates a form's City and State from Zip code using AJAX
*
* @return void
*/
function CityState_populate(zipEditID, indicatorID)
{
var http = AJAX_getXMLHttpObject();
var zip = document.getElementById(zipEditID).value;
var indicator = document.getElementById(indicatorID);
indicator.style.visibility = 'visible';
/* Build HTTP POST data. */
var POSTData = '&zip=' + urlEncode(zip);
/* Anonymous callback function triggered when HTTP response is received. */
var callBack = function ()
{
if (http.readyState != 4)
{
return;
}
if (!http.responseXML)
{
var errorMessage = "An error occurred while receiving a response from the server.\n\n"
+ http.responseText;
alert(errorMessage);
indicator.style.visibility = 'hidden';
return;
}
//alert(http.responseText);
/* Return if we have any errors. */
var errorCodeNode = http.responseXML.getElementsByTagName('errorcode').item(0);
var errorMessageNode = http.responseXML.getElementsByTagName('errormessage').item(0);
if (!errorCodeNode.firstChild || errorCodeNode.firstChild.nodeValue != '0')
{
if (errorCodeNode.firstChild.nodeValue != '-2')
{
var errorMessage = "An error occurred while receiving a response from the server.\n\n"
+ errorMessageNode.firstChild.nodeValue;
/* FIXME
* Do we have to popup an error dialog, if the zip lookup AJAX request fails?
*/
//alert(errorMessage);
indicator.style.visibility = 'hidden';
}
return;
}
var cityNode = http.responseXML.getElementsByTagName('city').item(0);
var stateNode = http.responseXML.getElementsByTagName('state').item(0);
if (document.getElementById('city'))
{
if (cityNode.firstChild)
{
document.getElementById('city').value = cityNode.firstChild.nodeValue;
}
else
{
document.getElementById('city').value = '';
}
}
if (document.getElementById('state'))
{
if (stateNode.firstChild)
{
document.getElementById('state').value = stateNode.firstChild.nodeValue;
}
else
{
document.getElementById('state').value = '';
}
}
indicator.style.visibility = 'hidden';
}
AJAX_callCATSFunction(http, 'zipLookup', POSTData, callBack, 0, null, false, false);
}
/* Returns the value of the radio button that is selected from a radio button
* group.
*/
function getCheckedValue(radioObj)
{
if (!radioObj)
{
return '';
}
var radioLength = radioObj.length;
if (typeof(radioLength) == 'undefined')
{
if (radioObj.checked)
{
return radioObj.value;
}
return '';
}
for (var i = 0; i < radioLength; i++)
{
if (radioObj[i].checked)
{
return radioObj[i].value;
}
}
return '';
}
/* Checks the specified radio button out of the radio button group by value. */
function setCheckedValue(radioObj, newValue)
{
if (!radioObj)
{
return;
}
var radioLength = radioObj.length;
if (typeof(radioLength) == 'undefined')
{
radioObj.checked = (radioObj.value == newValue.toString());
return;
}
for (var i = 0; i < radioLength; i++)
{
radioObj[i].checked = false;
if (radioObj[i].value == newValue.toString())
{
radioObj[i].checked = true;
}
}
}
function docjslib_getRealLeft(imgElem)
{
var xPos = eval(imgElem).offsetLeft;
var tempEl = eval(imgElem).offsetParent;
while (tempEl != null)
{
xPos += tempEl.offsetLeft;
tempEl = tempEl.offsetParent;
}
return xPos;
}
function docjslib_getRealTop(imgElem)
{
var yPos = eval(imgElem).offsetTop;
var tempEl = eval(imgElem).offsetParent;
while (tempEl != null)
{
yPos += tempEl.offsetTop;
tempEl = tempEl.offsetParent;
}
return yPos;
}
function findValueInArray(array, value)
{
for (var i = 0; i < array.length; i++)
{
if (array[i] == value)
{
return i;
}
}
return -1;
}
function findValueInSelectList(selectList, value)
{
for (var i = 0; i < selectList.length; i++)
{
if (selectList[i].value == value)
{
return i;
}
}
return -1;
}
if (Array.prototype.inArray == null)
{
Array.prototype.inArray = function(value)
{
var i;
for (i = 0; i < this.length; i++)
{
if (this[i] === value)
{
return true;
}
}
return false;
};
}
if (Array.prototype.push == null)
{
Array.prototype.push = function()
{
for (var i = 0; i < arguments.length; i++)
{
this[this.length] = arguments[i];
};
return this.length;
};
}
/* Event Cache uses an anonymous function to create a hidden scope chain.
* This is to prevent scoping issues.
*/
var EventCache = function()
{
var listEvents = [];
/* This open-brace MUST BE on the same line as the return. */
return {
listEvents : listEvents,
add : function (node, eventName, handler, useCapture)
{
listEvents.push(arguments);
},
flush : function()
{
var i, item;
for (i = listEvents.length - 1; i >= 0; i = i - 1)
{
item = listEvents[i];
if (item[0].removeEventListener)
{
item[0].removeEventListener(item[1], item[2], item[3]);
};
/* From this point on we need the event names to be prefixed
* with 'on". */
if (item[1].substring(0, 2) != 'on')
{
item[1] = 'on' + item[1];
};
if (item[0].detachEvent)
{
item[0].detachEvent(item[1], item[2]);
};
item[0][item[1]] = null;
};
}
};
}();
function addEvent(obj, type, fn, useCapture)
{
if (obj.addEventListener)
{
obj.addEventListener(type, fn, useCapture);
EventCache.add(obj, type, fn, useCapture);
}
else if (obj.attachEvent)
{
obj['e' + type + fn] = fn;
obj[type + fn] = function()
{
obj['e' + type + fn](window.event);
}
obj.attachEvent('on' + type, obj[type + fn]);
EventCache.add(obj, type, fn, useCapture);
}
else
{
//alert('Handler could not be attached.');
}
}
function removeEvent(obj, type, fn, useCapture)
{
if (obj.removeEventListener)
{
obj.removeEventListener(type, fn, useCapture);
return true;
}
if (obj.detachEvent)
{
return obj.detachEvent('on' + type, fn);
}
//alert('Handler could not be removed.');
}
function checkQuickSearchForm(form)
{
var fieldValue = document.getElementById('quickSearchFor').value;
var fieldLabel = document.getElementById('quickSearchLabel');
if (fieldValue == '')
{
fieldLabel.style.color = '#ff0000';
return false;
}
fieldLabel.style.color = '#000';
return true;
}
/* This executes all the ');
var js = working.substring(1,pos);
working = working.substring(pos);
pos = working.indexOf('