/**
 * suggestion in nwk project. author wangzhi. time 2008 september.
 */
 
//定义replaceAll方法
String.prototype.replaceAll = function(src, dest){
	if(this.length == 0){
		return "";
	}
	var regExp = new RegExp(src,"ig");
	return this.replace(regExp, dest);
}

String.prototype.trim= function(){  
    // 用正则表达式将前后空格  
    // 用空字符串替代。  
    return this.replace(/(^\s*)|(\s*$)/g, "");  
}

function suggestionInit(swId, goalAction) {
	//获取几个需要的ID
	window.swId = swId;
	window.goalAction = goalAction;
	
	//监控container
	createSuggestionDiv();
	//监控input
	var input = $(swId);
	input.autocomplete = "off";
	input.onkeyup = function () {
		if (keyCode != 37 && keyCode != 39) {
			try {
				if(!window.waiting){
					window.waiting = true;
					window.waitingId = window.setTimeout("ajaxFilter('" + this.value + "')", 200);
				}else{
					window.clearTimeout(window.waitingId);
					window.waitingId = window.setTimeout("ajaxFilter('" + this.value + "')", 200);
				}
			} catch (e) {
			}
			if(this.value == ''){
				$(window.containerId).style.display = "none";
			}
		}
	};
	input.onkeydown = function (_event) {
		var event = window.event || _event;
		window.keyCode = event.keyCode | event.which;
	};
	
	//监控body
	document.onclick = function (_event) {
		var event = window.event || _event;
		try {
			onClick(event);
		}
		catch (e) {
			return;
		}
	};
	window.lastInput = "";//记录用户最近一次输入的检索词
	window.ajaxsw = "";//记录每次发送请求后的AJAX检索词
	window.selectIndex = -1;//记录子DIV索引
	window.swArray = new Array();//记录用户发送Ajax请求返回的数组
	window.keyCode = 1;//捕获用户键盘代码
}
if (!window.$) {
	window.$ = function (id) {
		return document.getElementById(id);
	};
}
//创建下拉菜单的DIV
function createSuggestionDiv(){
	//将建议词列表容器加入回车符（文本框下面）
	var container = document.createElement("div");
	var swInput = $(window.swId);//用户查询输入文本框
	
	container.id = "sDiv_" + new Date().getTime();
	window.containerId = container.id;
	container.style.width = swInput.offsetWidth;
	container.style.border = "1px solid black";
	container.style.overflow = "visible";
	container.style.display = "none";
	container.style.position = "absolute";
	
	position = cumulativeOffset(swInput);
	container.style.left = position[1];
	container.style.top = position[0] + swInput.offsetHeight;
	
	//将建议词列表容器绑定至相应属性
	container.onmouseover = function (_event) {
		var event = window.event || _event;
		onOver(event);
	};
	document.body.appendChild(container);
}
//计算当前元素的位置
function cumulativeOffset(element) {
	var valueT = 0, valueL = 0;
	do {
		valueT += element.offsetTop  || 0;
		valueL += element.offsetLeft || 0;
      
      	//firefox没有currentStype的解决方案，20090819
		var borderWidth = 0;
		if(element.currentStyle){
			borderWidth = element.currentStyle.borderLeftWidth;
		}else if(window.getComputedStyle){
		    borderWidth = window.getComputedStyle(element, null).getPropertyValue("borderLeftWidth");
		    if(!borderWidth && borderWidth == ""){
		    	borderWidth = "0";
		    }
		}
		
		if(borderWidth != 0 && !(borderWidth == 'medium') && !(element.tagName.toLowerCase()=='input')){
			var pxIndex = borderWidth.indexOf('px');
			var width = borderWidth.substring(0,pxIndex);
			width = Number(width);
			valueL += width || 0;
		}
		element = element.offsetParent;
    } while (element);
    return [valueT,valueL]; //返回当前元素的Top和Left的值数组
}
/****************************入口函数**********************/
//将用户输入sw值传入JS，判断是否需要发送Ajax请求
function ajaxFilter(sw) {

	window.waiting = false;
	sw = $(window.swId).value;
	sw = trim(sw);
	var container = $(containerId);
	if (container == null) {
		return;
	}
	var children = container.childNodes;
	//捕获键盘事件
	if (isOperaKey(keyCode)) {
		if (!isNull(children)) {
			activeDiv(container);
		}
		selectItem(keyCode);
		return;
	}
	//如果本次与上次结果没变化，什么也不做就返回
	if (sw == lastInput) {
		return;
	}
	
	//如果用户输入的值为空，则清除并隐藏DIV，此处不必重画DIV
	if (isNull(sw)) {
		cleanDiv(container);
		hideDiv(container);
		return;
	}
	
	//如果ajax检索词为空(未发送过请求)或当前输入已与当初请求的ajax检索不匹配,当DIV中的项少于4项的时候并且此时页面缓存中
	//有128条，证明以当前sw首字或首字母开头的记录实际上大于512条，但是在后台缓存中没有加载至页面缓存中，故将sw作为input
	//再次发送至后台获取与sw相匹配的记录。符合以上三个条件的时候，则重新发送AJAX请求
	if (isNull(ajaxsw) || sw.indexOf(ajaxsw) != 0 || children == null) {
		//遍历用户当前输入字符串，有可能为纯中文，纯字母和中文字母混合，只要遇到中文，则送内容匹配检索，考虑建议词有可能为中英文混合
		sw = sw.toLowerCase();
		var checkType = getCheckType(sw);
		if (checkType < 0) {
			return;
		}
		sendAjax(sw, checkType);
	} else {
	
		//首先在页面匹配，如果匹配的数量不够，重新从服务器端获取
		if (swArray == null) {
			return;
		}
		reDrawDiv(sw);
		
		children = container.childNodes;
		var checkType = 1;
		if(children.length < 4 && swArray != null && swArray.length >= 128){
			sendAjax(sw, checkType);
		}
		
		if(sw.match(/.*[\u2e80-\u9fff].*/) && sw.match(/.*[a-zA-Z].*/)){
			sendAjax(sw, checkType);
		}
	}
}
/****************************业务函数****************************/
function getCheckType(sw) {
	//当用户的输入中包含汉字,则返回3
	var length = sw.length;
	for (var i = 0; i < sw.length; i++) {
		var c = sw.charAt(i);
		if (c < "a" || c > "z") {
			return 3;
		}
	}
	//当只输入一个字母时候不发送ajax请求,也不提示
	if (length < 2) {
		return -1;
	}

	//当用户输入的前两个字母都是声母,则返回2,只匹配缩写
	if (isConsonant(sw.charAt(0)) && isConsonant(sw.charAt(1))) {
		return 2;
	}

	//其他情况时候返回1,缩写和拼音都检查
	return 1;
}
//判断是否是一个字母
function isEngLetter(c) {
	if (c == null || c.length != 1) {
		return false;
	}
	c = c.toLowerCase();
	if ((c <= "z" && c >= "a") || (c <= "Z" && c >= "A")) {
		return true;
	}
	return false;
}
//判断一个字母是否辅音字母
function isConsonant(c) {
	if (isEngLetter(c)) {
		return "aeiouAEIOU".indexOf(c) < 0;
	}
	return false;
}
//判断一个字母是否元音字母
function isVowel(c) {
	if (isEngLetter(c)) {
		return "aeiouAEIOU".indexOf(c) >= 0;
	}
	return false;
}
//Ajax发送请求及不发送请求后均通过均函数开始绘制DIV，此函数主要负责调用清除DIV函数和绘制DIV函数
function reDrawDiv(sw) {
	if (isNull(swArray)) {
		return;
	}
	var container = $(containerId);
	cleanDiv(container);
	sortJson(swArray);
	fillDiv(sw, container);
	activeDiv(container);
}
//直接
function drawDiv(cs){
	if (isNull(cs)) {
		return;
	}
	var container = $(containerId);
	cleanDiv(container);
	sortJson(cs);
	fillDivCleverly(container, cs);
	activeDiv(container);
}
//发送Ajax请求
function sendAjax(sw, type) {
	window.lastInput = $(window.swId).value;
	var sUrl = goalAction;
	var sParam = "sw=" + sw + "&type=" + type;
	new Ajax.Request(sUrl, {parameters:sParam, method:"POST", onSuccess:function (response) {
		var txt = response.responseText;
		if(txt && (txt = txt.trim()).length > 0){
			var obj = eval(txt);
			if(obj.clever){
				drawDiv(obj.cs);
			}else{
				swArray = obj;
				ajaxsw = sw;
				reDrawDiv(sw);
			}
		}
	}, onFailure:function () {
		alert("failure");
	}, onException:function (e) {
		//alert(e.message);
	}});
}

//清除DIV
function cleanDiv(container) {
	var item = container.childNodes;
	for (var i = item.length; i > 0; --i) {
		container.removeChild(item[i - 1]);
	}
}

//对Json串按搜索次数排序
function sortJson(os){

	//倒序排序
	for (var i = 1 ; i < os.length ; ++ i) {
		for (var j = i ; j > 0 ; -- j) {
			var stj = parseInt(os[j].st);
			var stj1 = parseInt(os[j - 1].st);
			if(stj > stj1){
				var temp = os[j];
				os[j] = os[j - 1];
				os[j - 1] = temp;
			}
		}
	}
}

//绘制DIV
function fillDivCleverly(container, os) {
	var index = 0;
	var count = 1;
	for (var i = 0; count <= 10 && i < os.length; i++) {
		var curVal = os[i].c.toLowerCase();
		
		//排重
		for(var j = 0; j < i; j ++){
			var oldValue = os[j].c.toLowerCase();
			if(curVal == oldValue){
				continue;
			}
		}
		
		//绘制DIV
		var divItem = document.createElement("div");
		if (os[i].st == 0) {
			divItem.innerHTML = os[i].c
		} else {
			divItem.innerHTML = os[i].c + "(" + os[i].st + ")";
		}
		divItem.innerHTML = os[i].c

		divItem.className = "item";
		container.appendChild(divItem);
		count += 1;
	}
	//加入关闭功能
	if(container.childNodes.length > 0){
		addCloseContainerFunc(container);
	}
	//每次重新绘制完后，将键盘事件将用到的索引和保存匹配用户输入的数组置为初始状态
	selectIndex = -1;
}
//绘制DIV
function fillDiv(sw, container) {
	var index = 0;
	sw = sw.toLowerCase();
	var count = 1;
	for (var i = 0; count <= 10 && i < swArray.length; i++) {
		var curVal = swArray[i].c.toLowerCase();
		var curSpell = swArray[i].k.toLowerCase();
		
		//排重
		var cs = container.childNodes;
		var flag = false;
		for(var j = 0; j < i; j ++){
			var oldValue = swArray[j].c.toLowerCase();
			if(curVal == oldValue){
				flag = true;
				break;
			}
		}
		if(flag == true){
			continue;
		}
		
		//匹配
		if (curVal.indexOf(sw) == 0 || curSpell.indexOf(sw) == 0) {
			var divItem = document.createElement("div");
			if (swArray[i].st == 0) {
				divItem.innerHTML = swArray[i].c
			} else {
				divItem.innerHTML = swArray[i].c + "(" + swArray[i].st + ")";
			}
			divItem.innerHTML = swArray[i].c
			divItem.className = "item";
			container.appendChild(divItem);
			count += 1;
		}
	}
	
	//加入关闭功能
	if(container.childNodes.length > 0){
		addCloseContainerFunc(container);
	}
	//每次重新绘制完后，将键盘事件将用到的索引和保存匹配用户输入的数组置为初始状态
	selectIndex = -1;
}

//加入关闭Container的方法
function addCloseContainerFunc(container){
	//inner = inner + "<table width='100%' style='font-size:12px;'><tr><td></td><td align='right'><span onclick='hideDiv(container)'>关闭</span></td></tr></table>";
	var closeDiv = document.createElement("div");
	closeDiv.innerHTML = "<span onclick='hideDiv($(containerId))'><a href='javascript:' style='color:red;'>关闭</a></span>";
	closeDiv.className = "closeDiv";
	container.appendChild(closeDiv);
}
//激活DIV
function activeDiv(container) {
	var container = $(containerId);
	if (!isNull(container.childNodes)) {
		container.style.display = "block";
	} else {
		container.style.display = "none";
	}
}
//隐藏DIV
function hideDiv(container) {
	var container = $(containerId);
	if (isNull(swArray) && !isNull(container.childNodes)) {
		cleanDiv(container);
		container.style.display = "none";
	} else {
		container.style.display = "none";
	}
}
/**********************鼠标键盘事件函数*******************/
//鼠标点击事件
function onClick(click_event) {
	var txtInput = $(swId);
	var event = window.event || click_event;
	var src = event.srcElement || event.target;
	if (src == txtInput) {
		return;
	} else {
		if (src.className.indexOf("item") == 0) {
			txtInput.value = src.innerHTML.replaceAll("\\(\\d+\\)","");
		}
	}
	hideDiv($(containerId));
}
//鼠标悬停事件
function onOver(over_event) {
	var event = window.event || over_event;
	var src = event.srcElement || event.target;
	var children = $(containerId).childNodes;
	if (selectIndex != -1) {
		children[selectIndex].className = "item";
	} else {
		if (src.className == "item") {
			src.className = "item activeItem";
			src.onmouseout = function () {
				src.className = "item";
				src.onmouseout = null;
			};
		}
	}
	selectIndex = -1;
}
//键盘事件，选择Item
function selectItem(keyCode) {
	var container = $(containerId);
	var txtInput = $(swId);
	var childDivs = container.childNodes;
	if (container.style.display == "none" && childDivs.length == 0) {
		return;
	}
	//按键为上时
	if (keyCode == 38) {
		selectIndex -= 1;
		if (selectIndex == -2 || selectIndex == -1) {
			if (selectIndex == -1) {
				childDivs[selectIndex + 1].className = "item";
			}
			selectIndex = childDivs.length - 1;
		}
		childDivs[selectIndex].className = "item activeItem";
		if (selectIndex != childDivs.length - 1) {
			childDivs[selectIndex + 1].className = "item";
		}
		txtInput.value = childDivs[selectIndex].innerHTML.replaceAll("\\(\\d+\\)","");
		return;
	}
	//按键为下时
	if (keyCode == 40) {
		selectIndex += 1;
		if (selectIndex == childDivs.length) {
			childDivs[selectIndex - 1].className = "item";
			selectIndex = 0;
		}
		childDivs[selectIndex].className = "item activeItem";
		if (selectIndex > 0) {
			childDivs[selectIndex - 1].className = "item";
		}
		txtInput.value = childDivs[selectIndex].innerHTML.replaceAll("\\(\\d+\\)","");
		return;
	}
	//按键为大小键盘回车键
	if (keyCode == 13 || keyCode == 108) {
		if (selectIndex == -1) {
			return;
		}
		txtInput.value = childDivs[selectIndex].innerHTML.replaceAll("\\(\\d+\\)","");
		hideDiv($(containerId));
		return;
	}
	//按键为ESC时
	if (keyCode == 27) {
		hideDiv($(containerId));
		selectIndex = -1;
		return;
	}
	//选择完毕后，将keyCode置为空
	keyCode = "";
}
//去掉字符串两端的空格,包括全角空格
function trim(str) {
	return str.replace(/^[\s|　]*(.+[^\s^　])[\s|　]*$/, "$1");
}
//对象的判空
function isNull(obj) {
	return obj == null || obj.length == 0;
}
//判断是否为上('38')或下('40')或大键盘回车键('13')或小键盘回车键('108')或Esc('27')
function isOperaKey(keyCode) {
	return keyCode == 38 || keyCode == 40 || keyCode == 13 || keyCode == 108 || keyCode == 27;
}

