// ===================================================================
// Original Author: Peter Barkway
// WWW: http://www.baytree-cs.com/
// Version: 1.0c
// Date: 30/09/2007
//
// NOTICE: You may use this code for any purpose, commercial or
// private, without any further permission from the author. You may
// remove this notice from your final code if you wish, however it is
// appreciated by the author if at least my web site address is kept.
//
// You may *NOT* re-distribute this code in any way except through its
// use. That means, you can include it in your product, or your web
// site, or any other form where the code is actually being used. You
// may not put the plain javascript up on your site for download or
// include it in your javascript libraries for download. 
// If you wish to share this code with others, please just point them
// to the URL instead.
//
// Please DO NOT link directly to my .js files from your site. Copy
// the files to your server and use them there. Thank you.
// ===================================================================
//
///////2008-08-29/////////////http://www.shadowfax.bc.ca////////////Dale.C.Anderson///////////////
//
//-------
//
//  2008-08-29 (Dale): Original inclusion in global scripts library. Had to prefix some global variables, as they were conflicting with 
//                              other stuff in the library.
//
//  2009-07-01 (Dale): Added support for multiple instances on the same page, case insensitivity, and use by CSS class name instead of by div ID.
//
//  2009-08-18 (Dale): HEAVY modification. Added a 3rd (hidden) input, so that users doesnt get confused by english turning in to numbers. 
///                             Script is backwards compatible so as not to break existing admin sections. 
//
//
//
//
//  What is this for? 
//
//      This creates dropdowns that can either be selected from, like a normal
//      HTML select box, or can be be typed in, like a regular text box.
//      It's quite fantastic, really.
//      For whatever reason, this functionality was never included in HTML.
//      This is the best [simple + reliable] implimentation that I have found.
//
//
//   How to use it:
//         
//         Place the following 3 inputs inside of a div of css class "bcs_comboBox" (not case sensitive): 
//              one text box
//              one hidden input 
//              one select input 
//
//         This script will automatically combine the three input elements in to an "editable" dropdown list.
//         It basically places the select box behind the text box, so that you can either choose from a dropdown 
//         list, or type in your own value in to the input.
//
//         When an item is chosen from the dropdown list, it places the VALUE in to the hidden input, and the TEXT in to the text box.
//
//         You can have as many of these combo boxes on the page as you like, as long as they all have the "bcs_comboBox" css class. 
//         You can also call the Div's ID "bcs_comboBox" or start the div's ID with that, and append whatever else you want, 
//         and they should all work.
//
//         You may name your actual inputs anything you wish. The script figures out. The hidden input will be the one that ends up storing the "real" 
//         value that you're going to be retreiving, so that's the one you want to grab from. 
//
//
//
//  Example:  
//
//         <div id="my_important_div" class="bcs_comboBox">
//          <input type="hidden" id="my_id" name="my_id" value="" />
//          <input type="text" id="myEditableInput" name="myEditableInput" value="" />
//          <select id="choosie" name="choosie">
//           <option value="1">Big</option>
//           <option value="2">Fat</option>
//           <option value="3">Wide</option>
//          </select>
//         </div>
// 
//         When the above form submits, "my_id" will either contain a number, or will contain something that the user typed in.  
//
//-------
//
////////////////////////////////////////////////////////
 


var bcs_aSafeOnload = new Array();

function bcs_addLoadEvent(f){
	if  (window.onload){
		if (window.onload != bcs_SafeOnLoad){
			bcs_aSafeOnload[0] = window.onload;
			window.onload = bcs_SafeOnLoad;
		}    
		bcs_aSafeOnload[bcs_aSafeOnload.length] = f;
	}
	else {
		window.onload = f;
	}
}
function bcs_SafeOnLoad(){
	for (var i=0;i<bcs_aSafeOnload.length;i++)
		bcs_aSafeOnload[i]();
}


var bcs__objSelActive;
var bcs__offsetTop;
var bcs__offsetLeft;
var bcs__offsetLeftClip;
var bcs__comboBoxArray;
var bcs__blkName = 'bcs_comboBox';

function PseudoComboBox() {
	var browser = bcs_CheckBrowser();
	if(browser[0] == "Explorer") {
		bcs__offsetTop = 0;
		bcs__offsetLeft = 0;
		bcs__offsetLeftClip = 18;
	} else {
		bcs__offsetTop = 0;
		bcs__offsetLeft = 0;
		bcs__offsetLeftClip = 20;
	}
	bcs__objSelActive = false;
	

	if(document.getElementById){ 
		bcs__comboBoxArray = createComboList();		
		for(j=0; j<bcs__comboBoxArray.length;j++) {
			bcs_positionComboBox(bcs__comboBoxArray[j][0],bcs__comboBoxArray[j][1],bcs__comboBoxArray[j][2]);
		}
	} 

}

function createComboList() {
	// get all "bcs_comboBox" block elements in the document 
	var elements = null;
	var found = new Array();
	
	//var re = new RegExp('\\b'+bcs__blkName+'\\b');

	// Lets see if this works - I want to be able to name an element "bcs_comboBox2" 
	// so i can have multiple instances of combo boxes on a single page.
	// I also want it to be not case sensitive.
	var re = new RegExp("\\b" + bcs__blkName + "\\w*\\b", "i");
	
	if (document.getElementsByTagName) {
		elements = document.getElementsByTagName('*');
	} else if (document.all) {
		elements = document.all.tags('*');
	}
	if (elements) {
		for (var i = 0; i < elements.length; ++i) {
			if ((elements[i].id.search(re) != -1) || (elements[i].className.search(re) != -1)) {
				
				// Now we have a valid block element get the input and select id
				
				// For backwards compatibility: We are going to set the 'hidden' object to just be the text box for now.
				hiddenObj = elements[i].getElementsByTagName("input")[0];
				
				
				// But for real, lets go and find the hidden input, and the text box.
				for (var x = 0; x < elements[i].getElementsByTagName("input").length; x++){
					if(elements[i].getElementsByTagName("input")[x].type == "hidden"){
						hiddenObj = elements[i].getElementsByTagName("input")[x];
					} else {
						inpObj = elements[i].getElementsByTagName("input")[x];
						inpObj.onclick = bcs_repositionComboBox;
					}
				}
				
				selObj = elements[i].getElementsByTagName("select")[0]
				selObj.onmouseout = bcs_repositionComboBox;
				
				found[found.length] = [inpObj.id,selObj.id,hiddenObj.id];
				
				selObj.selectedIndex = -1;

			}
			
		}
	}
	return found;
}

function checkEvent(evt){
	var ie_var = "srcElement";
	var moz_var = "target";
	// "target" for Mozilla, Netscape, Firefox et al. ; "srcElement" for IE
	if(evt[moz_var]) {
		return [ evt[moz_var]['inputEl'],evt[moz_var]['selectEl'],evt[moz_var]['hiddenEl'] ];
	} else {
		return [ evt[ie_var]['inputEl'],evt[ie_var]['selectEl'] ,evt[ie_var]['hiddenEl'] ];
	}
}

function comboFocus(cId) {
	document.getElementById(cId).focus();
	return false;
}

function evtMozSelect(evt) {
	objs = checkEvent(evt);
	idEdit = objs[0];
	idSel = objs[1];
	idHidden = objs[2];
	////alert("212 " + idHidden);
	if(idSel.selectedIndex > -1) {
		// The order of these next two lines is critical for backwards compatibility with non-hidden input implimentations.
		document.getElementById(idEdit).value = idSel.options[idSel.options.selectedIndex].text;
		document.getElementById(idHidden).value = idSel.options[idSel.options.selectedIndex].value;
		idSel.selectedIndex = -1;
	}
	comboFocus(idEdit);
}

function evtIESelect(evt) {
	if(bcs__objSelActive) {
		objs = checkEvent(evt);
		idEdit = objs[0];
		idSel = objs[1];
		idHidden = objs[2];
	////alert("228 " + idHidden);
		if(idSel.selectedIndex > -1) {
			// The order of these next two lines is critical for backwards compatibility with non-hidden input implimentations.
			document.getElementById(idEdit).value = idSel.options[idSel.options.selectedIndex].text;
			document.getElementById(idHidden).value = idSel.options[idSel.options.selectedIndex].value;
			idSel.selectedIndex = -1;
		}

	
	if (document.getElementById("debug")) {
		document.getElementById("debug").value = idEdit + " . " + idSel + " . " + idHidden + " . " + document.getElementById(idHidden).value;
	}

		comboFocus(idEdit);
		bcs__objSelActive = false;
	} else {
		bcs__objSelActive = true;
	}
}

function comboIESelect(idEdit, idSel, idHidden) {
	if(idSel.selectedIndex > -1) {
		// The order of these next two lines is critical for backwards compatibility with non-hidden input implimentations.
		document.getElementById(idEdit).value = idSel.options[idSel.options.selectedIndex].text;
		document.getElementById(idHidden).value = idSel.options[idSel.options.selectedIndex].value;
		idSel.selectedIndex = -1;
	}
	
	if (document.getElementById("debug")) {
		document.getElementById("debug").value = idEdit + " . " + idSel + " . " + idHidden + " . " + document.getElementById(idHidden).value;
	}

	
	comboFocus(idEdit);
	bcs__objSelActive = false;
}

// 2009-08-21, Dale Anderson
// For non-hidden-input versions, this step is going to be totally redundant. Maybe find a way to skip this step for them.
function copyEditInputValueToHiddenInputValue(evt){
	objs = checkEvent(evt);
	//alert("257 " + objs);
	idEdit = objs[0];
	//alert("261 " + idEdit);
	idSel = objs[1];
	//alert("261 " + idSel);
	idHidden = objs[2];
	//alert("261 " + idHidden);
	if (document.getElementById(idHidden)) {
		document.getElementById(idHidden).value = document.getElementById(idEdit).value;
	}

	if (document.getElementById("debug")) {
		document.getElementById("debug").value = idEdit + " . " + idSel + " . " + idHidden + " . " + document.getElementById(idHidden).value;
	}
}



// This is triggered when a user types on the keyboard to navigate within a select list
function evtKey(evt) {
	objs = checkEvent(evt);
	idEdit = objs[0];
	idSel = objs[1];
	idHidden = objs[2];
//alert("271 " + idHidden);
	if(window.event)
		keyCode = window.event.keyCode;  //IE
	else
		keyCode = evt.keyCode;           //firefox

	if (keyCode == 13 || keyCode == 32) {
		comboIESelect(idEdit, idSel, idHidden);

	} else if (keyCode == 27) {
		idSel.selectedIndex = -1;
		comboFocus(idEdit);
		bcs__objSelActive = false;
	}
}

function findPos(obj) {
	// Credit for this function: http://www.quirksmode.org/js/findpos.html
	// Visit the URL for a complete tutorial on this function
	var curleft = curtop = parentbcs__offsetLeft = parentbcs__offsetTop = 0;
	if (obj.offsetParent) {
		 curleft = obj.offsetLeft
		 curtop = obj.offsetTop
		 curwidth = obj.offsetWidth;
		 while (obj = obj.offsetParent) {
				curleft += obj.offsetLeft
				curtop += obj.offsetTop
				if(obj.id) {
		 			parentbcs__offsetLeft = obj.offsetLeft;
		 			parentbcs__offsetTop = obj.offsetTop;
		 		}
		 }
	}
	return [curleft,curtop,curwidth,parentbcs__offsetLeft,parentbcs__offsetTop];
}

function bcs_positionComboBox(inpId, selId, hiddenID) {
	inpObj = document.getElementById(inpId);
	////alert(inpObj);
	selObj = document.getElementById(selId);
	////alert(inpObj);
	hiddenObj = document.getElementById(hiddenID);
	////alert(hiddenObj);
	
	// Positioning of the combotext boxes
	inpObj.style.marginRight = bcs__offsetLeftClip+'px';
	inpObj.style.position = "relative";
	selObj.style.position = "absolute";
	ofs=findPos(inpObj);                                        // Find the left/top & width of span
	selObj.style.top=(ofs[1]+bcs__offsetTop+(ofs[4]*-1))+'px';      // Set select box top location
	selObj.style.left=(ofs[0]+bcs__offsetLeft+(ofs[3]*-1))+'px';    // Set select box left location = curleft+bcs__offsetLeft+parentbcs__offsetLeft

	selObj.style.width=(inpObj.offsetWidth+bcs__offsetLeftClip)+'px';

	// The next line crops the select box and shows only the button
	selObj.style.clip = 'rect(0px, '+selObj.offsetWidth+'px, auto, '+ (selObj.offsetWidth-bcs__offsetLeftClip)+'px)';

	if(window.addEventListener){ // Mozilla, Netscape, Firefox
		selObj.addEventListener('change', evtMozSelect, false);
		selObj.addEventListener('keyup', evtKey, false);
		selObj.inputEl = inpObj.id;
		////alert("332 " + inpObj.id);
		selObj.selectEl = selObj;
		////alert("334 " + selObj);
		selObj.hiddenEl = hiddenObj.id;
		////alert("336 " + hiddenObj.id)

		inpObj.addEventListener('change', copyEditInputValueToHiddenInputValue, false);
		inpObj.inputEl = inpObj.id;
		inpObj.selectEl = selObj.id;
		inpObj.hiddenEl = hiddenObj.id; ////////////////// added .id - - WILL THIS WORK?;
		

	} else { // IE
		selObj.attachEvent('onchange', evtIESelect);
		selObj.attachEvent('onclick', evtIESelect);
		selObj.attachEvent('onkeypress', evtKey);
		selObj.inputEl = inpObj.id;
		selObj.selectEl = selObj;
		selObj.hiddenEl = hiddenObj.id;

//		inpObj.attachEvent('onkeypress', copyEditInputValueToHiddenInputValue);
		inpObj.attachEvent('onchange', copyEditInputValueToHiddenInputValue);
		inpObj.inputEl = inpObj.id;
		inpObj.selectEl = selObj.id;
		inpObj.hiddenEl = hiddenObj.id; ////////////////// added .id - - WILL THIS WORK?;

	}

	selObj.style.visibility = 'visible';
}

function bcs_CheckBrowser() {
	// Credit for this function: http://www.quirksmode.org/js/detect.html
	// Visit the URL for a complete tutorial on this function
	var BrowserDetect = {
		init: function () {
			this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
			this.version = this.searchVersion(navigator.userAgent)
				|| this.searchVersion(navigator.appVersion)
				|| "an unknown version";
			this.OS = this.searchString(this.dataOS) || "an unknown OS";
		},
		searchString: function (data) {
			for (var i=0;i<data.length;i++) {
				var dataString = data[i].string;
				var dataProp = data[i].prop;
				this.versionSearchString = data[i].versionSearch || data[i].identity;
				if (dataString) {
					if (dataString.indexOf(data[i].subString) != -1)
						return data[i].identity;
				}
				else if (dataProp)
					return data[i].identity;
			}
		},
		searchVersion: function (dataString) {
			var index = dataString.indexOf(this.versionSearchString);
			if (index == -1) return;
			return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
		},
		dataBrowser: [
			{ string: navigator.userAgent,
				subString: "OmniWeb",
				versionSearch: "OmniWeb/",
				identity: "OmniWeb"
			},
			{
				string: navigator.vendor,
				subString: "Apple",
				identity: "Safari"
			},
			{
				prop: window.opera,
				identity: "Opera"
			},
			{
				string: navigator.vendor,
				subString: "iCab",
				identity: "iCab"
			},
			{
				string: navigator.vendor,
				subString: "KDE",
				identity: "Konqueror"
			},
			{
				string: navigator.userAgent,
				subString: "Firefox",
				identity: "Firefox"
			},
			{
				string: navigator.vendor,
				subString: "Camino",
				identity: "Camino"
			},
			{   // for newer Netscapes (6+)
				string: navigator.userAgent,
				subString: "Netscape",
				identity: "Netscape"
			},
			{
				string: navigator.userAgent,
				subString: "MSIE",
				identity: "Explorer",
				versionSearch: "MSIE"
			},
			{
				string: navigator.userAgent,
				subString: "Gecko",
				identity: "Mozilla",
				versionSearch: "rv"
			},
			{     // for older Netscapes (4-)
				string: navigator.userAgent,
				subString: "Mozilla",
				identity: "Netscape",
				versionSearch: "Mozilla"
			}
		],
		dataOS : [
			{
				string: navigator.platform,
				subString: "Win",
				identity: "Windows"
			},
			{
				string: navigator.platform,
				subString: "Mac",
				identity: "Mac"
			},
			{
				string: navigator.platform,
				subString: "Linux",
				identity: "Linux"
			}
		]

	};
	BrowserDetect.init();

//  document.write('Browser name:'+BrowserDetect.browser);
//  document.write("<br />");
//  document.write('Browser version: '+BrowserDetect.version);
//  document.write("<br />");
//  document.write('OS name: '+BrowserDetect.OS);
//  document.write("<br />");

	return [BrowserDetect.browser,BrowserDetect.version,BrowserDetect.OS];
}

// Just here for backwards compatibility - some pages call this manually. 
function pcb_repositionComboBox(){
	bcs_repositionComboBox();
}

function bcs_repositionComboBox() {
	for(j=0; j<bcs__comboBoxArray.length;j++) {
		bcs_positionComboBox(bcs__comboBoxArray[j][0],bcs__comboBoxArray[j][1], bcs__comboBoxArray[j][2])
	}
}



bcs_addLoadEvent(PseudoComboBox);
