﻿/*关键字提示方法
参数：
e		DOM 2 标准的事件对象。当函数有多个参数时，这个事件对象必须是全局变量，变更名固定为 event，且从文档最顶层调用函数的地方传递进来，所以得 onkeyup="SearchMenu.suggest(event, this, '/suggest/extend?action=tip&scope=news', {q:this.value});" 这样才能在 FF 里用。
poper	发起元素
args	参数值对，每个属性名是参数名，每个值是参数的值，如二手房的用 {city:$('form_2nd').City.value, q:this.value}，会转化成 city=表单form_2nd中City项的值&q=当前格的值
*/
var suggest_selected = 0;
function suggest(e, poper, args)
{
	var e = e || window.event;
	var code = e.keyCode;
	var poperId = poper.id;
	//按的不是方向键时取关键字提示。方向键是37:"left", 38:"up",	39:"right", 40:"down"
	if(code == 13)
	{
		//回车，直接搜索
		if($('keyword').value != "")
		{
			var panel= $('divMenu');
			if (panel && (panel.style.display != "none"))
			{
				panel.style.display = "none";
			}
			setsearch('key',$('keyword').value);
		}
	}
	else if((code < 37) ||  (code > 40))
	{
		//每次生成新菜单时都把按键选中项的索引复原
		suggest_selected = 0;
		if(poper.value != "")
		{
			//IE 在请求地址相同时会从缓存中取数据，而发出新请求，变通一下，在请求地址上人为加个随机数，让每次请求地址都不同。不用时间戳的原因是 Date.parse(new Date()) 只精确到秒，若2次请求间隔小于1秒时仍然是相同请求。
			var url = "/house/suggest.php";
			var pars = 'q='+poper.value+'&cname='+searchcondition['cityname']+'&random='+Math.random();
			var myAjax = new Ajax.Request
			(
        		 url,
        		 {method: 'post', parameters: pars,onComplete: showSuggset}
    		);
		}

		
	}
	//按的是方向键时控制菜单中选项
	else
	{
		var panel = $('suggestsearch');
		if (panel)
		{
			var nodes = $('suggestsearch').childNodes;
			//提示出的关键字节点数，即共有几行
			var suggestNum = nodes.length;
			//关键字提示层的选中行要想能跟随按键变化，选中行数做成当前的局部变量不灵，每次按键都会重新回到局部变量的初始值，也得用个此函数范围外的变量，于是在 SearchWord 对象里再加个属性 suggest_selected 去记录，则选行的操作和城市菜单都一样了。
			if ((38 == code) || (40 == code))
			{
				//向上减行数
				if ((38 == code) && (1 < suggest_selected))
				{
					suggest_selected--;
					
				}
				//向下加行数
				if ((40 == code) && (suggest_selected < suggestNum))
				{
					suggest_selected++;
				}
				//找 suggestsearch 节点内的所有 a 把它们的 class 都清空，把当前选中行的 class 设成 suggest_selected。
				for (i=0; i< suggestNum; i++)
				{
					//行数是从1数起的，而节点数组的是从0数起的
					nodes[i].className = (i == (suggest_selected-1)) ? 'suggest_selected':'';
				}
				//焦点在输入格里时，按回车键是肯定要提交表单的，如果人为阻止表单提交，还得另外恢复表单的提交，干脆在选择时直接更新输入格的值
				var itemselected = nodes[suggest_selected-1].childNodes;
				$('keyword').value=itemselected[0].data;
			}
		}
	}
}

function showSuggset(originalRequest)
{
	var objxml = originalRequest.responseXML;
	var result = objxml.getElementsByTagName("result")[0];
  	if(result != null)
	{
		var msg = result.getElementsByTagName("msg")[0];
	}
	else
	{
		var panel= $('divMenu');
		if (panel)
		{
			panel.style.display = "none";
		}
		return;
	}
  	var msg = msg.firstChild.data;
  	if(msg == "")
  	{
  		var panel= $('divMenu');
		if (panel)
		{
			panel.style.display = "none";
		}
  		return;
  	}
	var arraySuggest = msg.split(",");
	//不仅是有返回的字符串，比如二手房没结果时也会返回 确实有返回的提示数据再生成提示层
	if (arraySuggest.length>0)
	{
		//这里的提示层要和输入框同宽，所以 ID 值改用 suggestsearch 了，在此页的 CSS 中单独定义它的固定宽度
		var str = '<div class="menubody" id="suggestsearch">';
		for (i=0; i<arraySuggest.length; i++)
		{//每行1个
			str += '<a href="javascript:void(0);" onclick="$(\'keyword\').value=\''+arraySuggest[i]+'\';clearClass();" onclick="$(\'keyword\').value=\''+arraySuggest[i]+'\';clearClass();">'+ arraySuggest[i] +'</a>';
		}
		str += '</div>';
		//onreadystatechange 的处理函数里是另一个执行范围了，所以要用全局变量名“SearchMenu”，而不能用 this 了。
		show($("keyword"), str);
		//生成层时再加上鼠标移入清理 .suggest_selected 类名的事件处理函数，有了按键处理后，按键如果选在某行时鼠标再移入，会出现按键选的行也是选中样式，鼠标悬停的行也是选中样式。只要在鼠标移入时把按键选中那行的 class 清空就行了。
	}
	//如果已有提示结果，但继续写了更多字后没结果了，要把以前的结果清掉，直接把层隐藏掉。这里隐藏菜单层没用 hide() 方法，因为 event 参数不好传递。
	else
	{
		var panel= $('divMenu');
		if (panel)
		{
			panel.style.display = "none";
		}
	}
}

function clearClass(e)
{
	//确实有按键选过再清理
	var e = e || window.event;
	var eventSource = e.target || e.srcElement;
	if ("keyword" != eventSource.id)
	{
		var panel= $('divMenu');
		if (panel && (panel.style.display != "none"))
		{
			panel.style.display = "none";
		}
	}
}
//关键字提示 end

/*显示菜单层
参数:
sourceobj 	发起元素，如 a 链接或 input 输入框，主要是根据触发的元素定位菜单
content	菜单内容，一段 HTML 代码，菜单层的样式应该做在这个参数的值里，方便不同的菜单显示成不同样式。
menuwidth		菜单宽度，单位为像素，若不指定则为发起元素的宽度。因为指定宽度比高度的情况更多，所以宽度作第3参数。
menuheight	菜单高度，单位为像素，若不指定则为自适应菜单内容的高度
功能: 创建并显示菜单层，这里生成的统一菜单 div 元素只管定位和尺寸，显示样式的设置由 content	菜单内容负责。
在这里统一 return false; 也不能让鼠标点链接时不做任何动作，还是得在链接当时的 onclick 里加  return false;
*/
function show(sourceobj, content, menuwidth, menuheight)
{
	var xy = getAbsPoint(sourceobj);
	var panel = $('divMenu');
	if (!panel)
	{
		panel= document.createElement("div");
		panel.id='divMenu';
		document.body.appendChild(panel);
	}

	panel.innerHTML = content;
	//和发起元素左对齐
	panel.style.left = xy.x + "px";
	//纵向加发起元素的高度
	panel.style.top = (xy.y + sourceobj.offsetHeight) + "px";
	if (menuheight)
	{
		panel.style.height = menuheight + "px";
	}
	if (!menuwidth)
	{
		var RealStyle = getRealStyle(sourceobj);
		//除了发起元素本身的宽，还得再加上它的左右 padding 和左右 border。实际上 RealStyle.width 返回的是形如 50px 这样带单位的值，且仅以 px 为单位的绝对值，反正 parseInt 转换整数遇到不是数字的自动停止，不影响。
		var menuwidth = parseInt(RealStyle.borderLeftWidth) + parseInt(RealStyle.paddingLeft) + parseInt(RealStyle.width) + parseInt(RealStyle.paddingRight) + parseInt(RealStyle.borderRightWidth);
	}
	//在页面内未明确定义发起元素的宽度时，FF 的 getComputedStyle() 能取到实际的宽度，而 IE 的 currentStyle 中的宽度空白，这时再赋值给 panel.style.width 就会报错。所以在这再容一下错，确实得到宽度值时再赋。IE 中得不到宽度值时，宽度是根据内容自动的。
	if (menuwidth > 0)
	{
		panel.style.width = menuwidth + "px";
	}
	panel.style.display = "block";
	//把发起元素的 ID 记在全局属性里，供隐藏菜单时判断用，需点击在文档中发起元素以外的部分才隐藏菜单
}

//取页面元素相对窗口的绝对位置
function getAbsPoint(e)
{
	var x = e.offsetLeft;
	var y = e.offsetTop;
	while(e = e.offsetParent)
	{
		x += e.offsetLeft;
		y += e.offsetTop;
	}
	return {'x': x, 'y': y};
}

//取元素的实际样式
function getRealStyle(node)
{
	var RealStyle;
	if (node.currentStyle)                            /*先试 IE 的 简单API */
	{
		RealStyle = node.currentStyle;
	}
	else if (window.getComputedStyle)              /* 再试 W3C API */
	{
		RealStyle = window.getComputedStyle(node, null);
	}
	return RealStyle;
}

//兼容 IE 和 FF 的事件注册。还没用到注销事件，先不写了。
function eventAdd(element, eventType, handler)
{
	if (document.addEventListener)
	{
		element.addEventListener(eventType, handler, false);
	}
	else if (document.attachEvent)
	{
		element.attachEvent("on" + eventType, handler);
	}
}
eventAdd(document, 'click', clearClass);