var vdSelect={

	idCounter:0,

	attach:function(obj, replaceList) {
		if (!obj.className.match('vdDontReplace')) {
			// first get height and width
			var width=obj.offsetWidth;
			var height=obj.offsetHeight-1;
			if (isMoz) {
				height-=4; //FIXME; depends on stylesheet
				// calculate position for moz to place replacement select
				var oTop=obj.offsetTop;
				var oLeft=obj.offsetLeft;
			}
			if (width && width>0 && height && height>0) {
				if (obj.className) {
					var listStyle=obj.className;
				} else {
					var listStyle='normal';
				}
				obj.className += ' vdReplaced';
				var ul = document.createElement('ul');
				ul.className = 'vdSelect';
				ul.style['width']=width+'px';
				ul.style['height']=height+'px';
				obj.onfocus = function() { vdSelect.doFocus(ul); }
				obj.onblur = function() { vdSelect.doBlur(ul); }
				obj.onkeydown = function(evt) { vdSelect.doKeyDown(ul, evt); }
				obj.onpropertychange = function() { vdSelect.updateList(ul, obj); }
				obj.onattrmodified = function() { vdSelect.updateList(ul, obj); }
				if (!obj.id) {
					obj.id='select_'+vdSelect.idCounter++;
				}
				var opts = obj.options;
				for (var i=0; i<opts.length; i++) {
					var selectedOpt;
					if (opts[i].selected) {
						selectedOpt = i;
						break;
					} else {
						selectedOpt = 0;
					}
				}
				for (var i=0; i<opts.length; i++) {
					var li = document.createElement('li');
					li.title=opts[i].text;
					var txt = document.createTextNode(opts[i].text);
					li.appendChild(txt);
					for (var ii in replaceList) {
						if (listStyle.match(new RegExp("\\b"+ii+"\\b"))) {
							li.innerHTML=replaceList[ii](opts[i].text);
							break;
						}
					}
					li.selIndex = opts[i].index;
					li.selectID = obj.id;
					li.onclick = vdSelect.clickSelect;
					if (i == selectedOpt) {
						li.className = 'selected';
						li.onclick = vdSelect.clickOpen;
					}
					if (!isMoz) { //window.attachEvent) {
						li.onmouseover = function() {
							this.className += ' hover';
						}
						li.onmouseout = function() {
							this.className = 
								this.className.replace(/\bhover\b/, '');
						}
					} else {
					//	ul.style.top=oTop+'px';
					//	ul.style.left=oLeft+'px';
					}
					ul.appendChild(li);
				}
				obj.parentNode.insertBefore(ul,obj);
			} else {
				window.status='w: '+width+'; h:'+height;
			}
		}
	},

	clickSelect:function(evt) {
		var event=getEvent(evt);
		vdSelect.selectMe(this);
		return vdSelect.cancelEvent(event);
	},

	clickOpen:function(evt) {
		var event=getEvent(evt);
		this.parentNode.className += ' selectOpen';
		this.onclick = vdSelect.clickSelect;
//		FIXME: line below adds keyboard shortcuts when ul is selected with mouse
//		but kills mouse select functionality somehow.
//		document.getElementById(this.selectID).focus();
		return vdSelect.cancelEvent(event);
	},	

	doFocus:function(obj) {
		obj.className += ' focus';
	},

	doBlur:function(obj) {
		obj.className = obj.className.replace(/\bfocus\b/, '');
		obj.className = obj.className.replace(/\bselectOpen\b/, '');	
	},

	doKeyDown:function(obj, evt) {
		var event=getEvent(evt);
		var charCode=(event.charCode ? event.charCode : ((event.keyCode) ? event.keyCode : event.which));
		var keyUp=38;
		var keyDown=40;
		var keyEnter=13;
		var keyPgUp=33;
		var keyPgDn=34;
		var lis = obj.getElementsByTagName('li');
		function openSelect() {
			if (!obj.className.match(/\bselectOpen\b/)) {
				obj.className += ' selectOpen';
				for (var i=0; i<lis.length; i++) {
					if (lis[i].className.match(/\bselected\b/)) {
						lis[i].className+=' hover';
						break;
					}
				}
			}
		}
		switch(charCode) {
			case keyUp:
				openSelect();
				for (var i=0; i<lis.length; i++) {
					if (lis[i].className.match(/\bhover\b/)) {
						if (i>0) {
							lis[i-1].className+=' hover';
							lis[i].className = 
								lis[i].className.replace(/\bhover\b/, '');
							window.status=lis[i].className;
							break;
						}
					}
				}

			break;
			case keyDown:
				openSelect();
				for (var i=0; i<lis.length; i++) {
					if (lis[i].className.match(/\bhover\b/)) {
						if (i<(lis.length-1)) {
							lis[i+1].className+=' hover';
							lis[i].className = 
								lis[i].className.replace(/\bhover\b/, '');
							window.status=lis[i].className;
							break;
						}
					}
				}

			break;
			case keyEnter:
				openSelect();
				obj.className = obj.className.replace(/\bselectOpen\b/, '');	
				var oldSelect=-1;
				var newSelect=-1;
				for (var i=0; i<lis.length; i++) {
					if (lis[i].className.match(/\bselected\b/)) {
						lis[i].className = 
							lis[i].className.replace(/\bselected\b/, '');
						oldSelect=i;
					}
				}
				for (var i=0; i<lis.length; i++) {
					if (lis[i].className.match(/\bhover\b/)) {
						lis[i].className+=' selected';
						lis[i].className = 
							lis[i].className.replace(/\bhover\b/, '');
						newSelect=i;
					}
				}
				if ((newSelect==-1) && (oldSelect!=-1)) {
					lis[oldSelect].className+=' selected';
				}
			break;
		}
	},

	selectMe:function(obj) {
		var lis = obj.parentNode.getElementsByTagName('li');
		for (var i=0; i<lis.length; i++) {
			if (lis[i] != obj) {
				lis[i].className='';
				lis[i].onclick = vdSelect.clickSelect;
			} else {
				vdSelect.setVal(obj.selectID, obj.selIndex);
				obj.className='selected';
				obj.parentNode.className = 
					obj.parentNode.className.replace(/\bselectOpen\b/, '');
				obj.onclick = vdSelect.clickOpen;
			}
		}
	},

	updateList:function(list, el) {
		var lis = list.getElementsByTagName('li');
		for (var i=0; i<lis.length; i++) {
			if (lis[i].selIndex==el.selectedIndex) {
				lis[i].className='selected';
				lis[i].onclick = vdSelect.clickOpen;
			} else {
				lis[i].className = '';
				lis[i].onclick = vdSelect.clickSelect;
			}
		}
	},

	blur:function() {
		var s = document.getElementsByTagName('ul');
		for (var i=0; i<s.length; i++) {
			s[i].className = 
				s[i].className.replace(/\bselectOpen\b/, '');		
		}
	},

	setVal:function(objID, selIndex) {
		var obj = document.getElementById(objID);
		obj.selectedIndex = selIndex;
		if (obj.onchange) {
			obj.onchange();
		}
	},

	cancelEvent:function(evt) {
		evt.cancelBubble=true;
		if (evt.returnValue) {
			evt.returnValue=false;
		} else if (evt.preventDefault) {
			evt.preventDefault();
		} else {
			return false;
		}
	},

	init:function(replaceList) {
		var s = document.getElementsByTagName('select');
		for (var i=0; i<s.length; i++) {
			vdSelect.attach(s[i], replaceList);
		}
		if (document.attachEvent) {
			document.attachEvent('onclick',vdSelect.blur);
		} else if (document.addEventListener) {
			document.addEventListener('click', vdSelect.blur);
		}
	}
}

