Javascript 实现无刷新联动菜单(select)的方法

所谓联动菜单,就是后一个下拉框的选项是根据前一个下拉框被选中的值来决定的,一个典型的应用就是省市联动菜单了,市的下拉选项是根据你选了哪个省来决定的,类似的需求我们经常遇到,相信许多新手都被这个问题困扰过。

其实,联动菜单的实现原理非常简单,本文详细介绍了联动菜单的实现方式,知道了原理,我们可以很容易地制作从XML、数据库加载的无限级联动菜单。

Javascript 实现无刷新联动菜单(select)的方法 – 示例

联动菜单的实现方法:

1.确定数据格式:

首先,我们介绍一下创建 Option 的语法:

 
var newOption = new Option(optionText, optionvalue);

根据上面的语法,我们知道 select 选项分 optionText 和 optionvalue 两个内容,optionText 即下拉框中我们看到的选项,而 optionvalue 则是提交的实际值。比如一个选项我们看到的是 “北京”,而实际提交的值是 “010”。

为了保持一致,我们确定选项的格式为:

 
{txt:"选项名", val:"选项值"}

那么一个选项组则是:

 
var childArr = [];
 
childArr['父选项值1'] = [
	{txt:"选项名1", val:"选项值1"}, 
	{txt:"选项名2", val:"选项值2"},
	{txt:"选项名3", val:"选项值3"},
	...
	{txt:"选项名n", val:"选项值n"}
]
 
childArr['父选项值2'] = [
	{txt:"选项名1", val:"选项值1"}, 
	{txt:"选项名2", val:"选项值2"},
	{txt:"选项名3", val:"选项值3"},
	...
	{txt:"选项名n", val:"选项值n"}
]

其中“父选项值”是父下拉列表选中的值。

注意:[ ] 和 {} 中的值是以“,” (逗号)分隔的,但是最后一个值后面不能有 “,” (逗号),否则语法错误, PHP 程序员要特别注意 !!!

2.根据传入的数组创建选项列表:

 
for (var i=0; i < len; i++)
{
	selectObj.options[i] = new Option(optionList[i].txt, optionList[i].val);
}

3.在设置选项之前,我们需要先将原有选项清空:

 
function removeOptions(selectObj)
{
	if (typeof selectObj != 'object')
	{
		selectObj = document.getElementById(selectObj);
	}
 
	// 原有选项计数
	var len = selectObj.options.length;
 
	for (var i=0; i < len; i++)
	{
		// 移除当前选项
		selectObj.options[0] = null;
	}
}

注意,这里不是用 selectObj.options[i] 而是用的 selectObj.options[0] ,由于在 options[0] 删除后,后面的选项就会补上,因此,我们只需要 selectObj.options[0] = null 。

4.设置一个提示选择项和默认选择项:

通常我们在下拉列表中会设置一个提示选择项,如:“请选择城市”,这个选项值为空,作用只是提示用户执行选择操作。

另外,下拉列表也需要能够设置默认选择项,即在页面加载的时候,设置选中状态的项目。

完整代码如下:

 
<script language="JavaScript" type="text/javascript">
<!--
 
/*
 * 说明:将指定下拉列表的选项值清空
 * 作者:CodeBit.cn ( http://www.CodeBit.cn )
 *
 * @param {String || Object]} selectObj 目标下拉选框的名称或对象,必须
 */
function removeOptions(selectObj)
{
	if (typeof selectObj != 'object')
	{
		selectObj = document.getElementById(selectObj);
	}
 
	// 原有选项计数
	var len = selectObj.options.length;
 
	for (var i=0; i < len; i++)
	{
		// 移除当前选项
		selectObj.options[0] = null;
	}
}
 
/*
 * 说明:设置传入的选项值到指定的下拉列表中
 * 作者:CodeBit.cn ( http://www.CodeBit.cn )
 *
 * @param {String || Object]} selectObj 目标下拉选框的名称或对象,必须
 * @param {Array} optionList 选项值设置 格式:[{txt:'北京', val:'010'}, {txt:'上海', val:'020'}] ,必须
 * @param {String} firstOption 第一个选项值,如:“请选择”,可选,值为空
 * @param {String} selected 默认选中值,可选
 */
function setSelectOption(selectObj, optionList, firstOption, selected)
{
	if (typeof selectObj != 'object')
	{
		selectObj = document.getElementById(selectObj);
	}
 
	// 清空选项
	removeOptions(selectObj);
 
	// 选项计数
	var start = 0;
	
	// 如果需要添加第一个选项
	if (firstOption)
	{
		selectObj.options[0] = new Option(firstOption, '');
 
		// 选项计数从 1 开始
		start ++;
	}
 
	var len = optionList.length;
 
	for (var i=0; i < len; i++)
	{
		// 设置 option
		selectObj.options[start] = new Option(optionList[i].txt, optionList[i].val);
 
		// 选中项
		if(selected == optionList[i].val)
		{
			selectObj.options[start].selected = true;
		}
 
		// 计数加 1
		start ++;
	}
 
}
 
//-->
</script>

示例代码:

 
<script language="JavaScript" type="text/javascript">
 
var cityArr = [];
cityArr['江苏省'] = [
		{txt:'南京', val:'南京'}, 
		{txt:'无锡', val:'无锡'},
		{txt:'徐州', val:'徐州'},
		{txt:'苏州', val:'苏州'},
		{txt:'南通', val:'南通'},
		{txt:'淮阴', val:'淮阴'},
		{txt:'扬州', val:'扬州'},
		{txt:'镇江', val:'镇江'},
		{txt:'常州', val:'常州'}
	];
cityArr['浙江省'] = [
		{txt:'杭州', val:'杭州'}, 
		{txt:'宁波', val:'宁波'},
		{txt:'温州', val:'温州'},
		{txt:'湖州', val:'湖州'}
	];
 
function setCity(province)
{	
	setSelectOption('city', cityArr[province], '-请选择-');
}
 
</script>
 
<select name="province" id="province" onchange="if(this.value != '') setCity(this.options[this.selectedIndex].value);">
	<option value="">-请选择-</option>
	<option value="江苏省">江苏省</option>
	<option value="浙江省">浙江省</option>
</select> 省
 
<select name="city" id="city">
	<option value="">-请选择-</option>
</select> 市

根据这个结构,设置好数据,我们可以很容易的实现无限级联动菜单。或者我们也可以将数据存放在文件或数据库中,通过 Ajax 获取数据。

Javascript 获取页面上选中的文字

在一些特殊应用中,我们需要获取页面上选中的文字,但是要实现这一需求,我们不得不面对那恼人的兼容问题,本文介绍了一个兼容性较好的解决方法。同时,也提供了一个在 FireFox 下获取 input 和 textarea 中选中文字的解决方案。

Javascript 获取页面上选中的文字 – 示例

获取选中的普通页面上的文字,可以用下面的方法:

 
<script type="text/javascript">
 
// 说明:获取页面上选中的文字
// 整理:http://www.CodeBit.cn
 
function getSelectedText() {
	if (window.getSelection) {
		// This technique is the most likely to be standardized.
		// getSelection() returns a Selection object, which we do not document.
		return window.getSelection().toString();
	}
	else if (document.getSelection) {
		// This is an older, simpler technique that returns a string
		return document.getSelection();
	}
	else if (document.selection) {
		// This is the IE-specific technique.
		// We do not document the IE selection property or TextRange objects.
		return document.selection.createRange().text;
	}
}
 
</script>

在 FireFox 下获取 input 或者 textarea 中选中的文字,可以用下面的方法:

 
<script type="text/javascript">
 
// 说明:FireFox 下获取 input 或者 textarea 中选中的文字
// 整理:http://www.codebit.cn
 
function getTextFieldSelection(e) {
	if (e.selectionStart != undefined && e.selectionEnd != undefined) {
		var start = e.selectionStart;
		var end = e.selectionEnd;
		return e.value.substring(start, end);
	}
	else return "";  // Not supported on this browser
}
 
</script>

MySQL 查询重复出现次数最多的记录

在有些应用里面,我们需要查询重复次数最多的一些记录,虽然这是一个很简单的查询语句,但是对许多初学者来说,仍然有些难度,特发此文章备查。

 
SELECT keyword, count( * ) AS count
FROM article_keyword
GROUP BY keyword
ORDER BY count DESC
LIMIT 20

此段查询语句返回 article_keyword 表中 keyword 重复次数(count) 最多的20条记录。

 
SELECT DISTINCT count( * ) AS count
FROM article_keyword
GROUP BY keyword
ORDER BY count DESC
LIMIT 6

此段查询语句返回 article_keyword 表中 keyword 的重复次数(count) 排名前 6 的数值。通过添加 DISTINCT 返回唯一记录。

一个不错的 Form 多选列表控件效果

很多人对 form 默认的多选框效果不太满意,因为选中和未选中的项目是在一起的,当选项较多时问题尤为明显,本文介绍的就是将可选项和选中项分开,并且可以通过操作按钮或者双击来移动选项,操作起来非常方便。

一个不错的 Form 多选列表控件效果 – 示例

首先将下面的代码放置在页面的<head>标签内:

 
<style type="text/css">


	.multipleSelectBoxControl span{	/* Labels above select boxes*/
		font-family:arial;
		font-size:11px;
		font-weight:bold;
	}
	.multipleSelectBoxControl div select{	/* Select box layout */
		font-family:arial;
		height:100%;
	}
	.multipleSelectBoxControl input{	/* Small butons */
		width:25px;	
	}
	
	.multipleSelectBoxControl div{
		float:left;
	}
		
	.multipleSelectBoxDiv
	</style>
 
<script type="text/javascript">
	
	/************************************************************************************************************
	(C) www.dhtmlgoodies.com, October 2005
	
	This is a script from www.dhtmlgoodies.com. You will find this and a lot of other scripts at our website.	
	
	Terms of use:
	You are free to use this script as long as the copyright message is kept intact. However, you may not
	redistribute, sell or repost it without our permission.
	
	Thank you!
	
	www.dhtmlgoodies.com
	Alf Magne Kalleland
	
	************************************************************************************************************/
	
		
	var fromBoxArray = new Array();
	var toBoxArray = new Array();
	var selectBoxIndex = 0;
	
	function moveSingleElement()
	{
		var selectBoxIndex = this.parentNode.parentNode.id.replace(/[^d]/g,'');
		var tmpFromBox;
		var tmpToBox;
		if(this.tagName.toLowerCase()=='select'){			
			tmpFromBox = this;
			if(tmpFromBox==fromBoxArray[selectBoxIndex])tmpToBox = toBoxArray[selectBoxIndex]; else tmpToBox = fromBoxArray[selectBoxIndex];
		}else{
		
			if(this.value.indexOf('>')>=0){
				tmpFromBox = fromBoxArray[selectBoxIndex];
				tmpToBox = toBoxArray[selectBoxIndex];			
			}else{
				tmpFromBox = toBoxArray[selectBoxIndex];
				tmpToBox = fromBoxArray[selectBoxIndex];	
			}
		}
		
		for(var no=0;no<tmpFromBox.options.length;no++){
			if(tmpFromBox.options[no].selected){
				tmpFromBox.options[no].selected = false;
				tmpToBox.options[tmpToBox.options.length] = new Option(tmpFromBox.options[no].text,tmpFromBox.options[no].value);
				
				for(var no2=no;no2<(tmpFromBox.options.length-1);no2++){
					tmpFromBox.options[no2].value = tmpFromBox.options[no2+1].value;
					tmpFromBox.options[no2].text = tmpFromBox.options[no2+1].text;
					tmpFromBox.options[no2].selected = tmpFromBox.options[no2+1].selected;
				}
				no = no -1;
				tmpFromBox.options.length = tmpFromBox.options.length-1;
											
			}			
		}
		
		
		var tmpTextArray = new Array();
		for(var no=0;no<tmpFromBox.options.length;no++){
			tmpTextArray.push(tmpFromBox.options[no].text + '___' + tmpFromBox.options[no].value);			
		}
		tmpTextArray.sort();
		var tmpTextArray2 = new Array();
		for(var no=0;no<tmpToBox.options.length;no++){
			tmpTextArray2.push(tmpToBox.options[no].text + '___' + tmpToBox.options[no].value);			
		}		
		tmpTextArray2.sort();
		
		for(var no=0;no<tmpTextArray.length;no++){
			var items = tmpTextArray[no].split('___');
			tmpFromBox.options[no] = new Option(items[0],items[1]);
			
		}		
		
		for(var no=0;no<tmpTextArray2.length;no++){
			var items = tmpTextArray2[no].split('___');
			tmpToBox.options[no] = new Option(items[0],items[1]);			
		}
	}
	
	function moveAllElements()
	{
		var selectBoxIndex = this.parentNode.parentNode.id.replace(/[^d]/g,'');
		var tmpFromBox;
		var tmpToBox;		
		if(this.value.indexOf('>')>=0){
			tmpFromBox = fromBoxArray[selectBoxIndex];
			tmpToBox = toBoxArray[selectBoxIndex];			
		}else{
			tmpFromBox = toBoxArray[selectBoxIndex];
			tmpToBox = fromBoxArray[selectBoxIndex];	
		}
		
		for(var no=0;no<tmpFromBox.options.length;no++){
			tmpToBox.options[tmpToBox.options.length] = new Option(tmpFromBox.options[no].text,tmpFromBox.options[no].value);			
		}	
		
		tmpFromBox.options.length=0;
		
	}
	
	
	
	function createMovableOptions(fromBox,toBox,totalWidth,totalHeight,labelLeft,labelRight)
	{		
		fromObj = document.getElementById(fromBox);
		toObj = document.getElementById(toBox);
		

		
		fromObj.ondblclick = moveSingleElement;
		toObj.ondblclick = moveSingleElement;

		
		fromBoxArray.push(fromObj);
		toBoxArray.push(toObj);
		
		var parentEl = fromObj.parentNode;
		
		var parentDiv = document.createElement('DIV');
		parentDiv.className='multipleSelectBoxControl';
		parentDiv.id = 'selectBoxGroup' + selectBoxIndex;
		parentDiv.style.width = totalWidth + 'px';
		parentDiv.style.height = totalHeight + 'px';
		parentEl.insertBefore(parentDiv,fromObj);
		
		
		var subDiv = document.createElement('DIV');
		subDiv.style.width = (Math.floor(totalWidth/2) - 15) + 'px';
		fromObj.style.width = (Math.floor(totalWidth/2) - 15) + 'px';

		var label = document.createElement('SPAN');
		label.innerHTML = labelLeft;
		subDiv.appendChild(label);
		
		subDiv.appendChild(fromObj);
		subDiv.className = 'multipleSelectBoxDiv';
		parentDiv.appendChild(subDiv);
		
		
		var buttonDiv = document.createElement('DIV');
		buttonDiv.style.verticalAlign = 'middle';
		buttonDiv.style.paddingTop = (totalHeight/2) - 50 + 'px';
		buttonDiv.style.width = '30px';
		buttonDiv.style.textAlign = 'center';
		parentDiv.appendChild(buttonDiv);
		
		var buttonRight = document.createElement('INPUT');
		buttonRight.type='button';
		buttonRight.value = '>';
		buttonDiv.appendChild(buttonRight);	
		buttonRight.onclick = moveSingleElement;	
		
		var buttonAllRight = document.createElement('INPUT');
		buttonAllRight.type='button';
		buttonAllRight.value = '>>';
		buttonAllRight.onclick = moveAllElements;
		buttonDiv.appendChild(buttonAllRight);		
		
		var buttonLeft = document.createElement('INPUT');
		buttonLeft.style.marginTop='10px';
		buttonLeft.type='button';
		buttonLeft.value = '<';
		buttonLeft.onclick = moveSingleElement;
		buttonDiv.appendChild(buttonLeft);		
		
		var buttonAllLeft = document.createElement('INPUT');
		buttonAllLeft.type='button';
		buttonAllLeft.value = '<<';
		buttonAllLeft.onclick = moveAllElements;
		buttonDiv.appendChild(buttonAllLeft);
		
		var subDiv = document.createElement('DIV');
		subDiv.style.width = (Math.floor(totalWidth/2) - 15) + 'px';
		toObj.style.width = (Math.floor(totalWidth/2) - 15) + 'px';

		var label = document.createElement('SPAN');
		label.innerHTML = labelRight;
		subDiv.appendChild(label);
				
		subDiv.appendChild(toObj);
		parentDiv.appendChild(subDiv);		
		
		toObj.style.height = (totalHeight - label.offsetHeight) + 'px';
		fromObj.style.height = (totalHeight - label.offsetHeight) + 'px';

			
		selectBoxIndex++;
		
	}
	
	
	
	</script>

然后将下面的代码放在页面的<body>标签内:

 
<form method="post" action="multiple_select.html">
<select multiple name="fromBox" id="fromBox">
	<option value="3">Finland</option>
	<option value="4">France</option>
	<option value="6">Mexico</option>
	<option value="1">Norway</option>
	<option value="5">Spain</option>	
	<option value="2">United Kingdom</option>
</select>
<select multiple name="toBox" id="toBox">
	<option value="12">Canada</option>
	<option value="13">Germany</option>
	<option value="11">United States</option>
</select>
</form>
<script type="text/javascript">
createMovableOptions("fromBox","toBox",500,300,'Available countries','Selected countries');
</script>
<p>You move elements by clicking on the buttons or by double clicking on select box items</p>

配置方法:
(1)用类似下面的代码创建两个多选列表

 
<select multiple name="fromBox" id="fromBox">
  <option value="3">Finland</option>
  <option value="4">France</option>
  <option value="6">Mexico</option>
  <option value="1">Norway</option>
  <option value="5">Spain</option>  
  <option value="2">United Kingdom</option>
</select>
<select multiple name="toBox[]" id="topBox">
  <option value="12">Canada</option>
  <option value="13">Germany</option>
  <option value="11">United States</option>
</select>

(2)用下面的javascript代码初始化设置:

 
<script type="text/javascript">
createMovableOptions("fromBox","toBox",500,300,'Available countries','Selected countries');
</script>

参数说明如下:
"fromBox" – 第一个多选列表的id(<select multiple name="fromBox" id="fromBox">)
"toBox" – 第二个多选列表的id(<select multiple name="toBox[]" id="toBox">)
500 – 控件的总宽度
300 – 控件的总高度
"Available countries" – 第一个多选列表的显示名称
"Selected countries" – 第二个多选列表的显示名称

提交表单的方法:

当提交表单时,我们希望只有选中的选项值被提交,所以需要一些javascript代码进行一些小的处理。

先在form标签中加入提交事件的处理:

<FORM onsubmit="selectItem()">

再加一段javascript代码:

 
function selectItem()
	{
		var obj = document.getElementById('toBox[]');
		for(var no=0;no<obj.options.length;no++){
			obj.options[no].selected = true;
		}
	}