//自定义控件DogFace集合,第一版本计划支持Tree、Layer、Tab以及Form美化
//Copyright (c) 2008 陈睿杰
//QQ：99352246

DogFace = new Object;

/*
 * Selector观察者
 */
DogFace.SelectorObserver = {
	selectors: [],
	hasHandle:false,
	active: null,
	add: function(selector){
		if(!this.selectors.include(selector)){
			this.selectors.push(selector);
			if(!this.hasHandle){
				this.addKeyEvent();
			}
		}
	},
	remove: function(selector){
		this.selectors = this.selectors.without(selector);
		if(this.selectors.size()==0){
			this.hasHandle = false;
			document.stopObserving("keydown");
		} 
	},
	addKeyEvent: function(){
		this.hasHandle = true;
		document.observe("keydown",function(event){	
			if(this.active){
				this.active.pressKey(event);
			}
		}.bind(this));	
	}
}

/*
 * 增强select控件，基于原始元素的位置、宽度，使用方法：
 * var new_select = new DogFace.Selector("原始select元素的id","箭头图片url",定位父元素,下拉选单最大高度（可选）)
 * 其中第二个参数可选，当下拉选单高度超过此值时，将自动出现滚动条，默认无限制
 * 外部可调用的接口为：
 * new_select.destroy() //取消美化，恢复原始select元素
 * 注意：此控件只起代理作用，真正提交的还是原始select的数据！
 */
DogFace.Selector = Class.create(
	{
		initialize: function(select,trigger_img,position_parent,max_height){
			this.select = $(select).setStyle({visibility:"hidden"});
			this.trigger_img = trigger_img;
			this.max_height = Object.isNumber? max_height:"auto";
			
			DogFace.SelectorObserver.add(this);
			this.makeSelect($(position_parent));
			this.makeWrap();
		},
		makeSelect: function(position_parent){
			var parent_top = position_parent.cumulativeOffset().top;
			var parent_left = position_parent.cumulativeOffset().left;
			position_parent.makePositioned();
			
			var selected = this.select[this.select.selectedIndex];
			var default_text = selected.firstChild ? selected.firstChild.nodeValue : '';
			
			this.element = new Element("input",{
				className:"text_field",
				value:default_text,
				readonly: true
			});
			
			this.element.setStyle(
				{
					position: "absolute",
					zIndex: 100,
					top: this.select.cumulativeOffset().top - parent_top + "px",
					left: this.select.cumulativeOffset().left - parent_left + "px",
					width: this.select.getWidth() - 38 + "px"
				}
			);

			this.element.observe("click",this.toggle.bind(this));
			this.select.insert({after: this.element});
			
			this.trigger = new Element("img",{src: this.trigger_img,className:"trigger"});
			this.trigger.setStyle({
				position: "absolute",
				top: this.element.positionedOffset().top + "px",
				left: this.element.positionedOffset().left + this.element.getWidth() -7 + "px"
			});
			
			this.trigger.observe("click",this.toggle.bind(this));
			
			this.element.insert({after:this.trigger});
		},
		makeWrap: function(){
			this.options = this.select.childElements().collect(
				function(item){
					return [item.value,item.firstChild ? item.firstChild.nodeValue.strip() : '',item.title];
				}
			);
			var list = new Element("ul");
			this.options.each(
				function(item){
					var option = new Element("li").update(new Element('a',{title:item[2],href:item[0]}).update(item[1]));
					option.observe("mouseover",function(event){
						var cur = $(this).up().down("li.hover");
						if(cur!=this){
							cur.removeClassName("hover");
							$(this).addClassName("hover");
						}
					});
					option.observe("click",function(event){
						this.select.value = item[0];
						this.element.value = item[1];
                        this.element.fire("content:changed",{value:item[0]});
					}.bind(this));
					list.appendChild(option);
				},this
			);
			list.down().addClassName("hover");
			this.wrap = new Element("div",{className:"all_wrap"}).update(list);
			
			this.element.insert({after:this.wrap.hide()});
			var height = this.wrap.getHeight();
			this.wrap.setStyle({
				position: "absolute",
				zIndex: 200,
				width: this.element.getWidth() + 15 + "px",
				overflowY: "auto",
				height: (Object.isNumber(this.max_height)&&height>this.max_height)? 
					this.max_height+"px" : "auto",
				top: this.element.positionedOffset().top + this.element.getHeight() + "px",
				left: this.element.positionedOffset().left - 7 + "px"
			});
            
            if(Prototype.Browser.IE){
                this.ieFix = this.wrap.insert({
                    after: '<iframe style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
                           'src="javascript:false;" frameborder="0" scrolling="no"></iframe>'
                }).next();

                this.ieFix.setStyle({
                    zIndex: 199,
                    width: this.wrap.getStyle("width"),
                    height: this.wrap.getStyle("height"),
                    left: this.wrap.getStyle("left"),
                    top: this.wrap.getStyle("top")
                });
            }
            
			
		},
		
		toggle: function(event){
			event.stop();
			var selectors = DogFace.SelectorObserver.selectors;
			selectors.without(this).invoke("hide");
			document.observe("click",function(){
				document.stopObserving("click");
				selectors.invoke("hide");
			}.bind(this));
			
			var cur = this.wrap.down("li.hover");
			var value_index = this.select.selectedIndex;
			var value = this.wrap.down("li",value_index);
			if(cur!=value){
				cur.removeClassName("hover");
				value.addClassName("hover");
			}
			
			this.wrap.toggle();
			this.ieFix && this.ieFix.toggle();
            
			this.toggleTrigger();
			
			if(this.wrap.visible()){
				this.active();
			};
			
		},
		
		hide: function(type){
			this.wrap.hide();
            this.ieFix && this.ieFix.hide();
			this.toggleTrigger();
		},
		
		toggleTrigger: function(){
			this.trigger.style.backgroundPosition = this.wrap.visible()?
				'-17px 0' : '0 0';
		},
		
		destroy: function(){
			DogFace.SelectorObserver.remove(this);
			[this.element,this.trigger,this.wrap].invoke("remove");

			this.select.setStyle({visibility:"visible"});
		},
		
		active: function(){
			DogFace.SelectorObserver.active = this;
		},
		
		pressKey: function(event){
			if(this.wrap.visible()){
				var cur = this.wrap.select("li.hover")[0];
				switch(event.keyCode){
					case Event.KEY_UP:
						var first = this.wrap.select("li:first-child")[0];
						if(cur!=first){
							cur.removeClassName("hover");
							var previou = cur.previous("li",0);
							previou.addClassName("hover");
							previou.scrollIntoView(false);
						};
						event.stop();
						break;
					case Event.KEY_DOWN:
						var last = this.wrap.select("li:last-child")[0];
						if(cur!=last){
							cur.removeClassName("hover");
							var next = cur.next();
							next.addClassName("hover");
							next.scrollIntoView(false);
						};
						event.stop();
						break;
					case Event.KEY_RETURN:
						var text = cur.down().firstChild.nodeValue;
						this.element.value = text;
                        
						this.select.value = this.options.find(function(option){
							return option[1]==text;
						})[0];
                        this.element.fire("content:changed",{
                            value: this.select.value
                        });
						this.element.removeClassName("error");
						this.element.blur();
						this.hide();
						event.stop();
				}
			}

		}
	}
);
