/*
 * This code is called from BHDisplayPicker to populate and render the auto-complete drop down
 * under the picker INPUT field. It handles all of the Ajax data population and event handling 
 * for that drop-down.
 * 
 * BHDisplayPicker calls pickerOnKeyUpHandler as the mail entry point onKeyUp() event.
 * 
 * The Ajax call fires to GetAutoComplete.cfm and UpdAutoComplete.cfm to get and persist options.
 * 
 * Chase Seibert
 * 03.07.2007
 * 117127 | Email Recipient Auto Complete
 * 
 */

// Constants
var BACKGROUND_NORMAL = "#FFFFFF";
var BACKGROUND_HIGHLIGHT = "#F7CF71";
var KEY_ENTER 	= 13;   
var KEY_DOWN 	= 40;   
var KEY_UP 		= 38;   
var KEY_ESCAPE	= 27;   
var KEY_DELETE  = 46;
var KEY_CONTROL = 17;
var KEY_TAB 	= 9;
var KEY_COMMA 	= 188;
var KEY_SEMICLN = 186;
var KEY_BACKSPACE = 8;
var TIME_BETWEEN_REQUESTS = 300;
var MAX_ROWS = 10;

var MAX_DROP_DOWN_HEIGHT = MAX_ROWS * 15;

// passed in from the calling code, the ID of the picker
var jsPickerID;
var pickerType = "email recipients";
var autoCompleteMode = "HISTORY";
var cancelBlur = false;

// a reference to the existing picker object created by BHDisplayPicker is grabbed using jsPickerID and stored here
var jsPickerObj;
var jsPickerInputObj;

// holds the state of the current drop-down
var dropDownDiv;
var dropDownData = new Array(MAX_ROWS);
var currentIndex = 0;
var maxIndex = 0;
var lastEventWasSelection = false;
var lastEventWasMultiSelection = false;
var unresolvedItems = false;

// holds the state relating to optimization of the call-backs
var thisRequestStartTime = getCurrentTimestamp();
var lastRequestLength = 0;

// objects for making the run-time HTTP request, and parsing the resuling XML (From GetAutoComplete.cfm)
var ajaxObj = new ActiveXObject("Microsoft.XMLHTTP");


/**
 * This is the main entry point for the BHDisplayPicker module, via the onKeyUp() event.
 */
function pickerOnKeyUpHandler (thisJsPickerID, pickerType, formName, formFieldName, parameterPrefix) {		

	// we may be dealing with a new/different picker than before, need to switch out state
	changePickerContext(thisJsPickerID, pickerType, formName, formFieldName, parameterPrefix);    			        	
		
	// check if the picker is currently NOT displayed
	if (isHidden()) {
    	    
		// set the highlight index to 0
		currentIndex = 0;	        	         	         	    
	}        	            	            	    
	
	// handle any key down event
	handleKeyPress(event.keyCode);	

	// redraw the auto-complete drop-down contents	
   	redraw();			 
}	

function pickerOnKeyDownHandler (thisJsPickerID, pickerType, formName, formFieldName, parameterPrefix) {		

	// we may be dealing with a new/different picker than before, need to switch out state
	changePickerContext(thisJsPickerID, pickerType, formName, formFieldName, parameterPrefix);    			        	
		
		
	switch (event.keyCode) {	
	
	  	case KEY_BACKSPACE:
	  	case KEY_DELETE:
	  	
	  		// see if you have anything selected
	  		if (document.selection.type == "Text") {	  		
		        // needed to persist deletions events to the picker
		        // but, need to wait until after the deletion event
		        setTimeout(commitChanges, 100); 		
	  		}
	  		break;
	  		
		default:
			break;
	}		 
}	

function commitChanges() {
	
	jsPickerObj.checkInput();
	jsPickerObj.commitEdits();
	hide();	 	
}


/**
 * This is a secondary entry point for the BHDisplayPicker module, via the onBlur() event.
 */
function pickerOnBlurHandler (thisJsPickerID, pickerType, formName, formFieldName, parameterPrefix) {    
	
	// we may be dealing with a new/different picker than before, need to switch out state
	changePickerContext(thisJsPickerID, pickerType, formName, formFieldName, parameterPrefix);
	
	//bhsWindowManagerObj.Debug("Event: OnBlur: " + cancelBlur);    			        				
   	
   	/* launch the picker, stupid hack to get around the fact that the onBlur on the parent DIV is getting
   	   launched BEFORE the click event on the picker menu */   	   	   	
   	if (cancelBlur) {
   		event.returnValue = false;
   	} else {   	
		setTimeout(blurPicker, 100);
   	}		
}


/**
 * This code is the same as what the BHDisplayPicker does onBlur() w/o the auto-complete enabled.
 * The only differences are:
 *    1. It's called after 100ms by pickerOnBlurHandler(), instead of right away, in order for the mouse event to be processed.
 *    2. It only gets called when something was not selected in the auto-complete UI
 *    3. It hides the auto-complete drop-down DIV
 */
function blurPicker() {
            
    if (!lastEventWasMultiSelection) {
	    hide();
        jsPickerObj.checkInput();       
    }  	   
    
    this.unresolvedItems = false;             
}


/**
 * This is called by both entry points (pickerOnKeyUpHandler and pickerOnBlurHandler) in order to possibly change the 
 * focus and state between multiple auto-complete pickers on the same page. Instead of stroring the context for all of them,
 * this code will switch back and forth.
 */
function changePickerContext (thisJsPickerID, thisPickerType, thisFormName, thisFormFieldName, thisParameterPrefix) {		
	
	// see if we are changing context to another picker
	if (thisJsPickerID != jsPickerID) {	    
		
		jsPickerID = thisJsPickerID;
		pickerType = thisPickerType;
		
		// 144248 | Distribution list are not working in Job -> Edit 
		jsPickerObj = GetBHDataPicker(thisFormName, thisParameterPrefix + thisFormFieldName);
		
		jsPickerInputObj = document.getElementById(jsPickerID + "_displayLayer");
		dropDownDiv = document.getElementById(thisJsPickerID + "_displayPopupLayer");
		currentIndex = 0;
		lastEventWasSelection = false;
		lastEventWasMultiSelection = false;
		unresolvedItems = false;
	}
}


/**
 * Handles the key press events for the auto-complete GUI (ex, up, down, enter, escape, new character for the filter)
 */
function handleKeyPress(keyCode) {
    
    /* this will be used to determine when an onBlur() event is because the user selected an auto-complete item,
     * or because they hit TAB or clicked off the picker. It will only be true for ENTER and MOUSE (on the div) events.
     */    
    lastEventWasSelection = false;
    lastEventWasMultiSelection = false;     

	switch (keyCode) {	
	
		case KEY_ENTER:   
			if (isHidden()) {
				showDefaultDropDown();					
			}
			else {
				onSelectHandler();	
			} 
			
			// 139661 | Auto-Complete - entering a name that is not auto-complete cached does not resolve when using ENTER. 
			if (maxIndex == 0) jsPickerInputObj.blur();
			
			break;
		
		case KEY_DOWN:
		
		    // increment the current index and redraw the picker
			showDefaultDropDown();			
			break;	
			
		case KEY_UP:
		
		    // decrement the current index and redraw the picker		
			currentIndex = (maxIndex + currentIndex - 1) % maxIndex;
			break;			
			
		case KEY_ESCAPE:
		
			hide();
			break;
			
	    case KEY_DELETE:
	    
	    	// needed to persist deletions events to the picker
	    	/*
	        jsPickerObj.checkInput();
            jsPickerObj.commitEdits();
            	    
			if (!isHidden()) {		        
				deleteCurrentlySelected();
				updateFilter();
			   	redraw();			   			
			} 
			*/
				   
	        break;
	        
	    case KEY_CONTROL:	    
	    
	    	// done with a multi-select
			hide();
	        break;
	        
	    case KEY_TAB:
	    	// nothing, but don't invoke the default case (causes empty picker to display when tabing ONTO a field
	    	break;
	    	
	    case KEY_COMMA:
	    case KEY_SEMICLN:
	    
	    	// if there is exactly one item in the drop-down, treat this just like an ENTER event
	    	// this allows the user to search down to the one they want, then press "," and it will select that item and move on
	    	if (maxIndex == 1) {
	    		onSelectHandler();	
	    	} else {
	    		this.unresolvedItems = true;	
	    	}
	    	break;	    
						
		default:
		
			// user has started or appended to a filter
			//bhsWindowManagerObj.Debug("Keypress: " + keyCode + ", ctrl: " + event.ctrlKey);
			currentIndex = 0;
			updateFilter();
			show();
			break;		
	}

}


/**
 * Displays a drop down when the user has not entered any data
 * The intention is to show them something useful, like their most recent
 * entries, or their TOP 10 most used (or both).
 */
function showDefaultDropDown() {

	// highlight the initial entry
	currentIndex = (currentIndex + 1) % maxIndex;		
	
	// special case, if the user has not typed anything yet, allow them to browse the auto-complete
	var filter = getFilterValue();
	if (isHidden() && filter == "*") {
		updateFilter();	
		currentIndex = 0;		    
	    show();
	}	
}


/**
 * Handles both selection and hover events via the mouse cursor
 */
function handleMouseEvent(thisIndex, isClicked) {    
	
    lastEventWasSelection = false;
    lastEventWasMultiSelection = false;
    	
	if (isClicked) {
	
		// select this item, the onSelectHandler can do all the work we need
		onSelectHandler();
		
	}
	else {
		
		// set the current index to the index the mouse is hovering over or clicking on and redraw the drop-down contents	
		currentIndex = thisIndex;
	   	redraw();	 	
   	}
}


/**
 * Redraws the drop-down DIV based on new content and/or new "hovered over" item
 */
function redraw() {

	// hide the drop-down if there is no data
	if (maxIndex <= 0) {
	    
    	hide();
    	
	} else {
	    
    	// highlight just the currently selected items, un-highlighting the rest
    	for (i=0; i < maxIndex; i++) {
    		var thisDiv = document.getElementById(jsPickerID + "_item_" + i);
    		var deleteImage = document.getElementById(jsPickerID + "_delete_" + i);
    		if (thisDiv != null) {
    		    if (i == currentIndex) {
    		    	thisDiv.style.backgroundColor = BACKGROUND_HIGHLIGHT;
    		    	deleteImage.style.visibility = 'visible';
    		    } else {  
        		   	thisDiv.style.backgroundColor = BACKGROUND_NORMAL;
        		   	deleteImage.style.visibility = 'hidden';
    		    }
    		}
    	}    	
    
	    var documentHeight = document.body.clientHeight;
	    var pickerOffset = dropDownDiv.offsetParent.offsetTop;
	    
	    //bhsWindowManagerObj.Debug("pickerOffset: " + pickerOffset);
	
	    if (pickerOffset + MAX_DROP_DOWN_HEIGHT > documentHeight
	    	&& pickerOffset - MAX_DROP_DOWN_HEIGHT > 0) {
	    	
	    	var newOffet = dropDownDiv.offsetHeight;
	    	if (newOffet == 0) newOffet = maxIndex * 12 + 4; 
	    	
	    	// display the drop down on TOP of the picker
			dropDownDiv.style.top = -1 * (newOffet + 18);
			dropDownDiv.style.borderTop = "1px solid";
			dropDownDiv.style.borderBottom = "none";   	
	    	
	    }      	    

	}	   
}


/**
 * Handles the event of actually selecting a particular option in the drop-down. 
 * Actually calls BHMain.js addEditValue() and commitEdits() for most of the work.
 */
function onSelectHandler() { 
		    
    // persist the fact that the current event is a selection, used for the onBlur() event handler
    lastEventWasSelection = true;   
	
	try {								

        // get the new record value and display values
		var value = dropDownData[currentIndex].value;
		var display = dropDownData[currentIndex].display;	
		var numTimesUsed = dropDownData[currentIndex].numTimesUsed + 1;
		var dateLastUsed = new Date();			
		
  	    // uses the existing code (in BHMain.js) to add/commit the new option
		jsPickerObj.addEditValue(value, display);		
		jsPickerObj.commitEdits();		 
		
		// persist in order to save the numTimesUsed + dateLastUsed
		//bhsWindowManagerObj.bhsAutoCompleteCacheObj.persist(pickerType, value, display);						
		bhsWindowManagerObj.bhsAutoCompleteCacheObj.putFromSelect(pickerType, value, display, numTimesUsed, dateLastUsed);								
				
	}
	catch (e) {
		
		bhsWindowManagerObj.Debug("Error in onSelectHandler: " + e.message);	
	}
	
	// unless the control key is held down, hide the DIV
	// allows for mult-select
	if (!event.ctrlKey) {		
	    jsPickerInputObj.blur();
	} else {
		lastEventWasMultiSelection = true;
		currentIndex = (currentIndex + 1) % maxIndex;
	}
	
    // set the focus back to the DIV
	jsPickerInputObj.focus();		
}


/**
 * Displays the auto complete drop-down
 */
function show () {
	            
    if (dropDownDiv != null) {
    	dropDownDiv.style.display = "block";
    }
}


/**
 * Hides the auto complete drop-down
 */
function hide () {
	
    if (dropDownDiv != null) {
    	dropDownDiv.style.display = "none";
    }     	
    
}          


function isHidden () {
	
    if (dropDownDiv != null) {
    	return dropDownDiv.style.display == "none";
    } 
    
    return true;    	    
} 

/**
 * Called by the key press event handler when the state of the filter should be updated
 * This may or may not kick off an Ajax data update, depending on when the last update
 * was performed. The folling code makes sure that the user has stopped typing for 
 * at least TIME_BETWEEN_REQUESTS ms.
 */
function updateFilter() {

	// only open a new ajax call if it's been more than X ms since the last one
	var timeSinceLastUpdate = getCurrentTimestamp() - thisRequestStartTime;
	if (timeSinceLastUpdate > TIME_BETWEEN_REQUESTS) {
	
		//bhsWindowManagerObj.Debug("Picker: updateFilter, time since last update: " + timeSinceLastUpdate + "ms, threshhold is " + TIME_BETWEEN_REQUESTS + " ms");
		doUpdate();

	} else {
	
		// if the threshold for doing an update has not been met, schedule this for when it has been
		setTimeout(updateFilter, TIME_BETWEEN_REQUESTS + 1);
	}
}

/**
 * Actually perform the Ajax update of the drop-down data, hitting GetAutoComplete.cfm
 */
function doUpdate() {
	
	if (this.unresolvedItems) return;
	if (bhsWindowManagerObj == null  || bhsWindowManagerObj.bhsAutoCompleteCacheObj == null) return;
	
	// see if this value is in the cache
	var cachedData = bhsWindowManagerObj.bhsAutoCompleteCacheObj.get(pickerType);
	if (cachedData != null) {
		
		renderFilteredData();    			
		
	} else {
    
		// get the value to filter by (ie, what the user has typed in)
		var thisFilter = getFilterValue();
    
        // perform the actual Ajax call, with a call back to onAjaxCallback() on completion
        ajaxObj.open("GET", "/BullhornStaffing/Forms/GetAutoComplete.cfm", true);
        ajaxObj.onreadystatechange = onAjaxCallback;    	
        ajaxObj.setRequestHeader("filter", thisFilter); 
        ajaxObj.setRequestHeader("pickerType", pickerType); 
        ajaxObj.setRequestHeader("autoCompleteMode", autoCompleteMode); 	        
    	ajaxObj.send(thisFilter);
    	
    	// print a debug message to the window manager console
    	bhsWindowManagerObj.Debug("Request: GetAutoComplete.cfm?filter=" + thisFilter);    
    	
	}
}

/**
 * Filters the data in the cache and renders it to the drop-down
 */
function renderFilteredData() {
	
	var thisFilter = getFilterValue();	
	var cachedData = bhsWindowManagerObj.bhsAutoCompleteCacheObj.get(pickerType);	
	if (cachedData != null) {
		var filteredData = filterData(cachedData, thisFilter);
		RenderData(filteredData);
	}	
	
	// show the picker once the original data is parsed
	if (filteredData.length > 0) 
		show();
}


/**
 * Handles the event of the GetAutoComplete.cfm returning data
 */
function onAjaxCallback() { 	

	try {

        // this call back can be called multiple times, check to make sure that the HTTP request has completed	
	    if (ajaxObj.readyState == 4) {
	        
	        // also check to make sure it was successful
	        if (ajaxObj.status == 200) {	        
	        	
	        	// parse the results       
       			ParseJSON(ajaxObj.responseText);
       			renderFilteredData();
	        	
	        } else {
	        	
	        	// special case - see if the error was related to missing schema 
	        	if (ajaxObj.responseText.indexOf("Invalid object name 'BH_AutoComplete'") > 0) {
	        		alert("GET: This private label has autoCompleteEnabled turned on, but the database is missing the BH_AutoComplete schema.");
	        	} else {
		            alert("There was a problem retrieving the XML data:\n" + ajaxObj.statusText);
	        	}
	        }
	    }	    
	}
	catch (e) {
	
		bhsWindowManagerObj.Debug("Error in onAjaxCallback: " + e.message);
	}	    
}


/**
 * Parses the JSON response from GetAutoComplete.cfm and persists the rows in the global cache
 */
function ParseJSON (JSONText) {
	
	// short circuit on empty dataset
	if (JSONText == "") {
		
		// just create a blank array placeholder for now
		bhsWindowManagerObj.bhsAutoCompleteCacheObj.initialize(pickerType);
		return;
	}
		
    // de-serialize the JSON
    // todo: use a parser?
	var p = eval("(" + JSONText + ")");		
	
	for (var i=0; i < p.records.length; i++) {
		
		bhsWindowManagerObj.bhsAutoCompleteCacheObj.putFromDatabase(
			p.records[i].pickerType, 
			p.records[i].value, 
			p.records[i].display,
			p.records[i].numTimesUsed,
			p.records[i].dateLastUsed
			);
	}
	
}


/**
 * Renders the passed array in the drop-down and displays them
 */
function RenderData (records) {

	// reset the drop-down html
	dropDownDiv.innerHTML = "";
	dropDownData = new Array(records.length);
	var headers = 0;
	for (j=0; j < records.length; j++) {	
	
		if (records[j].isSectionHeader) {
			
			appendSectionHeader(records[j].display);
			headers++;
			
		} else {
			
			// parse the attributes and append them to the down down
			appendToDropDown(
				j - headers,
				records[j].value,
				records[j].display		
			);
			
		}
		
	}		
	
	if (records.length == 0) {
		maxIndex = 0;
		hide();
	}

    // re-draw the drop-down	
	redraw();
}


function appendSectionHeader(display) {
	
	// append this div to the picker html
	dropDownDiv.innerHTML += "<DIV "
		+ "style='width: 100%'>"
		+ "<I><B>"
		+ display
		+ ":"	
		+ "</B></I>"		
    	+ "</DIV>";		
}


/**
 * Helpers function, extracted from RenderData in case we want to populate these from other places
 * ex: adding invidual rows to the end not from the database
 */
function appendToDropDown(j, value, display) {
	
	maxIndex = j + 1;
		
	// record the ID of this record for later access (ie, when you select one of the options)
	dropDownData[j] = new Object();
	dropDownData[j].display = display;		
	dropDownData[j].value = value;
	
	var recordDisplay = display; 
	recordDisplay = recordDisplay.replace("<", "&lt;");
	recordDisplay = recordDisplay.replace(">", "&gt;");	
	recordDisplay = hightLightSearchTerm(recordDisplay, getFilterValue());	

	// append this div to the picker html
	dropDownDiv.innerHTML += 
		"<DIV id=\"" + jsPickerID + "_item_" + j + "\" style='cursor: hand; width: 100%;' "
			+ "onmouseover='handleMouseEvent(" + j + ", false);' "		
			+ "onclick='handleMouseEvent(" + j + ", true); blurPicker();' "
			+ "onmousedown='cancelBlur = true;' " 
			+ "onmouseup='cancelBlur = false;' "		
			+ "> "
			//+ "<IMG id=\"" + jsPickerID + "_delete_" + j + "\" SRC='/Bullhorn/Images/Icons/Delete_small.gif' style='float: right; visibility: hidden;' onclick='event.cancelBubble = true; deleteSelected();'> "
			+ "<SPAN id=\"" + jsPickerID + "_delete_" + j + "\" style='float: right; visibility: hidden;' onclick='event.cancelBubble = true; deleteSelected();'>delete</SPAN>"
			+ recordDisplay	
		+ "</DIV>";    	
}

function deleteSelected() {
    	    
	if (!isHidden()) {		        
		deleteCurrentlySelected();
		updateFilter();
	   	redraw();			   			
	} 	
	
    // set the focus back to the DIV
    jsPickerInputObj.focus();   	
}

function hightLightSearchTerm(recordDisplay, filter) {		
					
	if (filter != "*") {		
		
		try {
			var regex = new RegExp("(^| |&lt;)(" + filter + ")", "gi");		
			return recordDisplay.replace(regex, "$1<B><I>$2</I></B>");		
		} 
		catch (e) {
			bhsWindowManagerObj.Debug("Error in hightLightSearchTerm: " + e.message);	
		}
	}
		
	return recordDisplay;
}


/**
 * Returns the current filter value the user has typed in
 */
function getFilterValue() {
    
	thisDiv = document.getElementById(jsPickerID + "_displayLayer");    
	var filter = trim(thisDiv.innerText.replace(/.*(;|,)/g, ""));
	filter = filter.replace(/\*/gi, ".*");
	
	// account for spaces
	filter = filter.replace(" ", ".*? ");
	
	// strip special characters, such as []()+?$^\
	filter = filter.replace(/(\[|\]|\(|\)|\+|\?|\$|\^|\\)/gi, "");
		
	// get the LAST value in the semi-colon seperated list
	//bhsWindowManagerObj.Debug("filter: " + filter);
    return filter == "" ? "*" : filter;
}


/**
 * String trim function, removes whitespace from start and end
 */
function trim(value) {

    return value.replace(/^\s+/g, "").replace(/\s+$/g, "");
}


/**
 * Helper method to get the current timestamp in ms. Used by updateFilter to compare 
 * the current time to a previous time using just a subtraction operation
 */
function getCurrentTimestamp () {

	var now = new Date();
	var msSinceMidnight = 60 * 60 * 1000 * now.getHours() + 60 * 1000 * now.getMinutes() + 1000 * now.getSeconds() + now.getMilliseconds();
	return msSinceMidnight;
}


/**
 * Does the filtering of the user's query against the cached data in dataArray (from BHAutoCompleteCache)
 * Only returns at most MAX_ROWS entries (global constant)
 */
function filterData(inputArray, filter) {
	
	var filteredData = new Array();
	dataArray = inputArray;
	
	if (dataArray.length <= 0) return dataArray;
	
	// default case - no filter entered
	if (filter == ''
		|| filter == '*') {
		
		// match ANYTHING
		filter = '.*';
		
		// resort dataArray to show the most frequently used items
		dataArray = bhsWindowManagerObj.bhsAutoCompleteCacheObj.sortByMostUsed(inputArray);		
		filteredData[0] = formatDataRow("", "Most frequently used", true);
		var retArray = appendFilteredItems(filteredData, dataArray, filter, 4);

		// resort dataArray to show the most recently used items		
		filteredData[retArray.length] = formatDataRow("", "Most recently used", true);		
		var recentArray = bhsWindowManagerObj.bhsAutoCompleteCacheObj.sortByDateLastUsed(inputArray);
		retArray = appendFilteredItems(retArray, recentArray, filter, 4);
		return retArray;
		
	} else {
		
		// todo: replace * with .*, and ' ' with .* as well
		return appendFilteredItems(filteredData, dataArray, filter, MAX_ROWS);
	}
}


/**
 * Appends an array of items to a given array
 */
function appendFilteredItems(filteredData, dataArray, filter, maxRows) {
		
	var regex;
	var offset = filteredData.length;
	var j = 0;
	var i = 0;
	while (i < dataArray.length) {
		
		 var thisDisplay = dataArray[i].display;		 
		 var thisValue = dataArray[i].value;			 
	
		 // don't bomb out on potential regex errros	 
 		 try {
			 // for some reason, I need to instantiate this everytime, even though it should be stateless 		 	
			regex = new RegExp('(^| |<)' + filter, "gi");
		 } 
		 catch (e) {
			bhsWindowManagerObj.Debug("Error in appendFilteredItems: " + e.message);	
		 }		 		 
		 
		 if (regex != null
		     && regex.test(thisDisplay)) {		 
		 	
		    //bhsWindowManagerObj.Debug(dataArray[i].display + " -> " + dataArray[i].numTimesUsed);	 		 		 	
		 	
		 	var newIndex = j + offset;
		 	filteredData[newIndex] = formatDataRow(thisValue, thisDisplay, false);
		 	
		 	j++;
		 }
		 
		 if (j > maxRows) {
		 	return filteredData;
		 }
		 
		 i++;		 
	}
	
	return filteredData;	
}


/**
 * Formats a single row object ultimately being returned by filterData
 */
function formatDataRow(value, display, isSectionHeader) {
	
	var newObject = new Object();
	newObject.value = value;		 	
	newObject.display = display;		 	
	newObject.isSectionHeader = isSectionHeader;
	return newObject;
}

function deleteCurrentlySelected () {
	
	// get the currently selected item, and delete it from the cache (and database)
	var value = dropDownData[currentIndex].value;	
	bhsWindowManagerObj.bhsAutoCompleteCacheObj.remove(pickerType, value);
	
}
