/**
 * 将字典数据以树型显示到指定容器
 */
var MyTree = {cache: {}};
MyTree.dfop = {
	valueField : "text",	// 值字段，id text value
    valueInput : false,		// 值输入对象，设置后，text放入container，valueFiled指定的字段放的valueInput
	width : 0,
    data: null,
	scroll : true,
    usecached: true,
    cascadecheck: false,
	parentOptional : false,	// 父节点可选择
	rootText : false,
	scrollHeight : 180,
    inputClass: "ac_input",
    resultsClass: "ac_results",
    loadingClass: "ac_loading",
    async: true,
    onComplete: function() {}
};

/**
 * 创建字典树
 * @param {} container 树放值的容器，可以是input、select、div，格式为jquery选择器
 * @param {} code 字典编码
 * @param {} defValue 默认选中值
 * @param {} settings 配置，参考默认配置MyTree.dfop
 * @return {}
 */
MyTree.createTree = function(container, code, defValue, settings) {
    var container = $(container);
    var t = container.attr("type");
    var tag = container.attr("tagName").toLowerCase();
    
    var dfop = {url: "/constant.do?code=" + code};
    $.extend(dfop, MyTree.dfop);
    $.extend(dfop, settings);
    
    $.ajaxSetup({
    	async : dfop.async
    });
     
    // 加载数据
    if (dfop.data == null) {
        if (MyTree.cache[code] == null || !dfop.usecached) {
		    if (tag != 'select' && tag != 'input')
		        container.text("数据加载中......");
            dfop.onLoadComplete = function(data) {
            	if (dfop.rootText) {
            		data = [{
						id:'0', //ID只能包含英文数字下划线中划线
						text: dfop.rootText,
						value:'0',
						showcheck:false,
						checkstate:0, 
						hasChildren:true,
						isexpand:true,
						complete:true,
						childNodes: data
					}];	
            	}
                MyTree.cache[code] = data;
                return data;
            }
        } else {
            dfop.data = MyTree.cache[code];
        }
    }

	if (t == "text") {
		var input = container.get(0);
		return new $.TreeContainer(input, dfop);
	} else if (tag == 'select') {
        var selectObj = container.get(0);
        if (dfop.data)
            MyTree.fillSelect(selectObj, dfop.data, defValue, dfop.valueField, dfop.parentOptional);
         else {
            $.getJSON(dfop.url, function(data) {
                MyTree.cache[code] = data;
                MyTree.fillSelect(selectObj, data, defValue, dfop.valueField, dfop.parentOptional);
            });
         }
	} else {
		container.treeview(dfop);
	}
	
	dfop.onComplete();

    $.ajaxSetup({
    	async : true
    });
    
	return container;
}

MyTree.fillSelect = function(selectObj, data, defValue, valueField, parentOptional) {
	if (data && data.length > 0) {
	    var l = data.length;
	    for (var i = 0; i < l; i++) {
	        MyTree.buildOption(selectObj, data[i], defValue, valueField, parentOptional);
	    }
	}   
}
MyTree.buildOption = function(selectObj, item, defValue, valueField, parentOptional) {
    // 没子元素或可以选择父元素
    if (!item.hasChildren || parentOptional) {
		var option = new Option(item.text, item[valueField]);
		selectObj.options.add(option);
		// 选中默认值
		if (option.value == defValue)
			selectObj.selectedIndex = selectObj.options.length - 1;
    }
	if (item.hasChildren && item.childNodes) {
		var l = item.childNodes.length;
		for (var k = 0; k < l; k++) {
			MyTree.buildOption(selectObj, item.childNodes[k], defValue,
					valueField);
		}
	}
}

$.TreeContainer = function(input, options) {
	// Create $ object for input element
	var $input = $(input).attr("readonly", "readonly")
			.addClass(options.inputClass);
			
	var hasFocus = 0;
	var select = $.TreeContainer.Select(options, input, $input.val());

	var blockSubmit;

	// only opera doesn't trigger keydown multiple times while pressed, others
	// don't work with keypress at all
	$input.focus(function() {
				hasFocus++;
			}).blur(function() {
				hasFocus = 0;
				if (!select.active())
					select.hide();
			}).click(function() {
				// show select when clicking in a focused field
				if (hasFocus++ > 0 && !select.visible())
					select.show();
			});
}

$.TreeContainer.Select = function(options, input, select) {
	var listItems, active = -1, needsInit = true, element;

	// Create results
	function init() {
		if (!needsInit)
			return;
		if (input.selecter) {
			input.selecter.unbind;
			input.selecter = false;
		}
		input.selecter = this;
		
		element = $("<div/>").hide()
            .addClass(options.resultsClass)
            .css("position", "absolute")
            .css("text-align", "left")
            .appendTo(document.body);
        treeElement = $("<div/>").appendTo(element);
            
		options.onnodeclick = function(item) {
			if (options.valueInput) {
                $(options.valueInput).val(item[options.valueField]);
                $(input).val(item.text);
			} else {
                $(input).val(item[options.valueField]);
			}
			input.focus();
			active = -1;
			element.hide();
		}
		treeElement.treeview(options).mouseout(function() {
					active = -1;
				}).mouseover(function() {
					active = 1;
				});

		if (options.width > 0)
			element.css("width", options.width);

		needsInit = false;
	}
	init();

	return {
		active : function() {
			return active > 0;
		},
		hide : function() {
			element && element.hide();
			active = -1;
		},
		visible : function() {
			var visibled = element && element.is(":visible");
			return visibled;
		},
		current : function() {
			return element.getTCT();
		},
		show : function() {
			var offset = $(input).offset();
			element.css({
				width : typeof options.width == "string" || options.width > 0
						? options.width
						: $(input).width(),
				top : offset.top + input.offsetHeight,
				left : offset.left
			}).show();
			if (options.scroll) {
				if ($.browser.msie
						&& typeof document.body.style.maxHeight === "undefined") {
					var listHeight = 0;
					listItems.each(function() {
								listHeight += this.offsetHeight;
							});
					var scrollbarsVisible = listHeight > options.scrollHeight;
					list.css('height', options.scrollHeight);
					if (!scrollbarsVisible) {
						// IE doesn't recalculate width when scrollbar
						// disappears
						listItems.width(list.width()
								- parseInt(listItems.css("padding-left"))
								- parseInt(listItems.css("padding-right")));
					}
				}
			}
		},
		unbind : function() {
			element && element.remove();
		}
	};
}

var getType = function(object) {
	var _t;
	return ((_t = typeof(object)) == "object" ? object == null && "null"
			|| Object.prototype.toString.call(object).slice(8, -1) : _t)
			.toLowerCase();
}

function isString(o) {
	return getType(o) == "string";
}

