	// moves one or more selected options from a one select element optgroup to another select element optgroup
	function moveOptgroupOptions(selectIDTo,selectIDFrom){
		var selectFrom = document.getElementById(selectIDFrom);
		var selectTo = document.getElementById(selectIDTo);

		var selectTo_optgroups;
		var optgroupTo;
		var optgroupFromLabel;

		// loop from select element
		for (var count=0; count < selectFrom.length; count++){
			// if selected option
			if (selectFrom.options[count].selected == true){
				//get parentnode (in this case should be optgroup)
				optgroupFromLabel = selectFrom.options[count].parentNode.getAttribute("label");
				// selectTo optgroups
				selectTo_optgroups = getOptgroups(selectTo);
				// loop selectTo optgroups
				for (var icount=0; icount < selectTo_optgroups.length; icount++){
					optgroupTo = selectTo_optgroups[icount];
					if(optgroupTo.getAttribute("label") == optgroupFromLabel){
						optgroupTo.appendChild(selectFrom.options[count], null);
						sortOptgroupOptions(selectTo,optgroupTo);
						break;
					}
				}
			count--;
			}
		}
	}
	
	// moves one or more selected options from a one select element to another (if not in optgroups)
	function moveOptions(selectIDTo,selectIDFrom){
		var selectFrom = document.getElementById(selectIDFrom);
		var selectTo = document.getElementById(selectIDTo);
		
		for (var i=0; i < selectFrom.length; i++){
			// if selected option
			if (selectFrom.options[i].selected == true){
				selectTo.appendChild(selectFrom.options[i]);
				sortOptions(selectIDTo);
				i--;
			}
		}	
	}
	
	// sorts options in a select box (as long as they are not inside optgroups)
	function sortOptions(selectElementID){
		var selectElement = document.getElementById(selectElementID);
		var tempArray = new Array();
		
		for (i=0; i < selectElement.length; i++){
			tempArray[i] = new Option(selectElement.options[i].text,selectElement.options[i].value);
		}
		
		tempArray.sort(compareOptionText);
		
		for (i=0; i < selectElement.length; i++){
			var option = document.createElement("option");
			option.setAttribute("value",tempArray[i].value);
			option.innerHTML = tempArray[i].text;
			selectElement.replaceChild(option,selectElement.options[i]);
		}
	}

	/*
	  * returns >0 if option1 is later alphabetically
	  * 0 if same string
	  * <0 if if option2 is later alphabetically
	*/
	function compareOptionText(option1,option2) {
		 // textual comparison
		 return option1.text!=option2.text ? option1.text<option2.text ? -1 : 1 : 0;
	 }

	// sorts Options in an optgroup (alphabetically ascending)
	function sortOptgroupOptions(selectElement,optgroupElement){
		var currentOption;
		var optgroup_firstchild_position;
		removeWhitespaceNodesFromChildNodes(optgroupElement);
		var totalOptgroupChildren = optgroupElement.childNodes.length;
		var tempArray = new Array();
		var finished = false;

		// get position to start and end ordering on
		for (count=0; count < selectElement.options.length; count++){
			currentOption = selectElement.options[count];
			if (optgroupElement.getAttribute("label").match(currentOption.parentNode.getAttribute("label"))){
				//position of option in select option array
				optgroup_firstchild_position = count;
				break;
			}
		}

		// enter new order into temporary array
		for (i=optgroup_firstchild_position; i < optgroup_firstchild_position+totalOptgroupChildren; i++){
			tempArray[i] = new Option(selectElement.options[i].text,selectElement.options[i].value);
		}
		// sort options using given function
		tempArray.sort(compareOptionText);
		// make copies of sorted options back to list
		for (i=0; i < totalOptgroupChildren; i++){
			var option = document.createElement("option");
			option.setAttribute("value",tempArray[i].value);
			option.innerHTML = tempArray[i].text;
			optgroupElement.replaceChild(option,selectElement.options[optgroup_firstchild_position + i]);
		}
	}

	// removes all whitespace nodes from childnodes of a given element
	function removeWhitespaceNodesFromChildNodes(Element){
		var notWhitespace = /\S/;
		for (i=0; i< Element.childNodes.length; i++){
			if ((Element.childNodes[i].nodeType == 3) && (!notWhitespace.test(Element.childNodes[i].nodeValue))){
				// that is, if it's a whitespace text node
				Element.removeChild(Element.childNodes[i]);
				i--;
			}
		}
	}

	// gets all optgroups from a select element (returns them in an array)
	function getOptgroups(selectElement){
		var optgroup_array = new Array();
		var optgroup_size = 0;
		var currentOption;

		for (var count=0; count < selectElement.childNodes.length; count++){
			currentOption = selectElement.childNodes[count];
			if (currentOption.nodeName.toLowerCase() == "optgroup"){
				optgroup_array[optgroup_size] = currentOption;
				optgroup_size++;
			}
		}
		return optgroup_array;
	}

	// sets all options in a select Element to selected
	function selectAllOptions(selectElementID){
		var selectElement = document.getElementById(selectElementID);
		for (count=0; count < selectElement.length; count++){
			selectElement.options[count].selected = true;
		}
	}
	
	// get an elements first child element
	function get_firstchild(n){
		x = n.firstChild;
		while (x.nodeType!=1){
			x=x.nextSibling;
		}
		return x;
	}