注册 登录
编程论坛 jQuery论坛

手把手教你做下拉菜单[龙族首发][本人独创ajax下拉菜单][多个社区加为精华]

爱像深蓝 发布于 2007-10-31 21:45, 4241 次点击

手把手教你做下拉菜单[龙族首发][本人独创ajax下拉菜单]
市面上讲述下拉菜单的文章多如牛毛,且使用下拉菜单的网站也非常之多,但在下看来,90%的网站和教程使用了如下代码:

function MM_reloadPage(init) { //reloads the window if Nav4 resized
if (init==true) with (navigator) {if ((appName=="Netscape")&&(parseInt(appVersion)==4)) {
document.MM_pgW=innerWidth; document.MM_pgH=innerHeight; onresize=MM_reloadPage; }}
else if (innerWidth!=document.MM_pgW || innerHeight!=document.MM_pgH) location.reload();
}
MM_reloadPage(true);
// -->

function MM_findObj(n, d) { //v4.0
var p,i,x; if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document);
if(!x && document.getElementById) x=document.getElementById(n); return x;
}

function MM_showHideLayers() { //v3.0
var i,p,v,obj,args=MM_showHideLayers.arguments;
for (i=0; i<(args.length-2); i+=3) if ((obj=MM_findObj(args[i]))!=null) { v=args[i+2];
if (obj.style) { obj=obj.style; v=(v=='show')?'visible':(v='hide')?'hidden':v; }
obj.visibility=v; }
}

在下因公司的一个项目需要学习完ajax这个最流行的web技术之后,独辟蹊径想出一个集完全无刷新实时更新的下拉菜单,而且这个下拉菜单可以无限的可扩展性.下面请看源码:
1.数据库,为了方便大家下载,在下所使用的是access,即想学习的朋友可以直接下载我包含数据库mdb文件的rar包,解压至IIS的发布目录即可直接查看效果.
2.表结构如下图:

3.在下使用的是最传统的两层结构:
数据库连接层DAL,Model数据模型层
DAL db.cs源码:

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.OleDb;
using System.IO;

/// <summary>
/// DB 的摘要说明
/// </summary>
public class DB
{
private string strConn = System.Configuration.ConfigurationSettings.AppSettings["strConn"] + AppDomain.CurrentDomain.BaseDirectory + System.Configuration.ConfigurationSettings.AppSettings["strDBPath"];
private OleDbConnection cn = null;
public DB()
{
try
{
cn = new OleDbConnection(strConn);
}
catch (OleDbException oe)
{
Console.Write(oe.Message);
}
}

/// <summary>
/// 通过Sql脚本执行数据库增,删,改操作
/// </summary>
/// <param name="strSql">Sql脚本</param>
/// <returns>true表示执行成功,false表示执行失败</returns>
public bool ExecCmdBySql(string strSql)
{
bool foo = true;

try
{
cn.Open();
OleDbCommand cmd = new OleDbCommand();
cmd.CommandText = strSql;
cmd.Connection = cn;
cmd.ExecuteNonQuery();
}
catch (OleDbException oe)
{
foo = false;
Console.Write(oe.Message);
}
finally
{
cn.Close();//关闭接连
}

return foo;

}


/// <summary>
/// 通过查询得到数据集
/// </summary>
/// <param name="strSql">查询Sql脚本</param>
/// <param name="ds">数据集引用</param>
/// <param name="tableName">表名</param>
/// <returns>true表示成功查询得到数据集,false表示查询失败</returns>
public bool GetDataSetByQuery(string strSql,ref DataSet ds,string tableName)
{
bool foo = true;
try
{
cn.Open();
OleDbCommand cmd = new OleDbCommand();
cmd.CommandText = strSql;
cmd.Connection = cn;
OleDbDataReader reader = cmd.ExecuteReader();
ds.Load(reader, LoadOption.OverwriteChanges, new string[] { tableName });
}
catch (OleDbException oe)
{
foo = false;
Console.Write(oe.Message);
}
finally
{
cn.Close();
}

return foo;
}

/// <summary>
/// 通过查询得到首行数据编号
/// </summary>
/// <param name="strSql">Sql脚本</param>
/// <param name="id">编号</param>
/// <returns></returns>
public bool GetScalarByQuery(string strSql, ref long id)
{
bool foo = true;
try
{
cn.Open();
OleDbCommand cmd = new OleDbCommand();
cmd.CommandText = strSql;
cmd.Connection = cn;
Object obj = cmd.ExecuteScalar();
if (!obj.ToString().Equals(""))
{
id = (long)obj;
}
else
{
id = 1;
}
}
catch (OleDbException oe)
{
foo = false;
Console.Write(oe.Message);
}
finally
{
cn.Close();
}

return foo;
}

}


注:只考虑access数据库Sql连接的情况故有三个方法;

model层: CMenu类

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

/// <summary>
/// CMenu 的摘要说明
/// </summary>
public class CMenu
{
private long menu_id; //菜单编号
private string menu_name;//菜单名称
private long menu_parentID;//父级菜单编号
public long Menu_id
{
get { return menu_id; }
set { menu_id = value; }
}
public string Menu_name
{
get { return menu_name; }
set { menu_name = value; }
}
public long Menu_parentID
{
get { return menu_parentID; }
set { menu_parentID = value; }
}
public CMenu()
{
menu_id = -1; //菜单编号
menu_name = "";//菜单名称
menu_parentID = -1;//父级菜单编号
}

/// <summary>
/// 得到当前记录应该插入的编号
/// </summary>
/// <returns>true表示执行成功,false表示执行失败</returns>
public bool GetID()
{
bool foo = false;

DB db = new DB();

string strSql = "select max(menu_id) from menu";


if (db.GetScalarByQuery(strSql, ref menu_id))
{
foo = true;
}

return foo;
}

public bool Insert2DB()
{
bool foo = false;

if (!GetID())
{
return foo;
}

string strSql = "insert into menu ";
string strAttribute = " (menu_id";
string strValue = " (" + menu_id;

if (!menu_name.Equals(""))
{
strAttribute += " ,menu_name";
strValue += ",'" + menu_name + "'";
}

if (-1 != menu_parentID)
{
strAttribute += " ,menu_parentID";
strValue += "," + menu_parentID;
}

strAttribute += ")";
strValue += ")";
strSql += strAttribute + strValue;

DB db = new DB();

if (db.ExecCmdBySql(strSql))
{
foo = true;
}

return foo;
}

public bool Delete2DB()
{
bool foo = false;

string strSql = "delete from menu where menu_id = " + menu_id;

DB db = new DB();

if (db.ExecCmdBySql(strSql))
{
foo = true;
}

return foo;
}

public bool Delete2DB(string strConn)
{
bool foo = false;

string strSql = "delete from menu " + strConn;

DB db = new DB();

if (db.ExecCmdBySql(strSql))
{
foo = true;
}

return foo;

}

public bool Update2DB()
{
bool foo = false;

string strSql = "update menu set menu_id = menu_id ";

if (!menu_name.Equals(""))
{
strSql += " menu_name = '" + menu_name + "'";
}

if (-1 != menu_parentID)
{
strSql += " menu_parentID = " + menu_parentID;
}

strSql += " where menu_id =" + menu_id ;

DB db = new DB();

if (db.ExecCmdBySql(strSql))
{
foo = true;
}

return foo;
}

public bool Query2DB(ref DataSet ds,string strColunm ,string strConn)
{
bool foo = false;

string strSql = "select * from ";

if (!strColunm.Equals(""))
{
strSql ="select " + strColunm + " from menu ";
}

if (!strConn.Equals(""))
{
strSql += strConn;
}

DB db = new DB();

if (db.GetDataSetByQuery(strSql, ref ds, "menu"))
{
foo = true;
}

return foo;
}

}

4 回复
#2
爱像深蓝2007-10-31 21:46
回复:(爱像深蓝)手把手教你做下拉菜单[龙族首发][本...

前台代码 Default.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>DropDownMenu</title>
<link href="css/base.css" rel="stylesheet" type="text/css" />
<script type="text/javascript">
var left = 0;
var top = 0;
function InitHtmlControl()
{
GetParentMenu();
}

function GetParentMenu()
{
_Default.GetMainMenu(CallBack_GetParentMenu);
}

function CallBack_GetParentMenu(res)
{
var strOut = res.value;

document.getElementById("divTitleMenu").innerHTML = strOut;
}

function GetSubMenu(curCon,id)
{
var mybt = curCon.parentNode;

left = mybt.offsetLeft;
top = mybt.offsetTop;
while(mybt = mybt.offsetParent)
{
top += mybt.offsetTop;
left += mybt.offsetLeft;
}


_Default.GetSubMenu(id,CallBack_GetSubMenu);
}

function CallBack_GetSubMenu(res)
{
var strOut = res.value;
var div = document.getElementById("divSubMenu");
div.style.left = left;
div.style.top = top;
div.innerHTML = strOut;
}

function Go2Conent(id)
{//一般而言这里是为了传入一个编号得到一个相应的URL然后跳转,即"ContentMenu.aspx?menu_id="+id ; 这样的东东.这里没有写组织菜单的数据表,故只能向下向写这个的东东
document.getElementById("divContent").innerHTML = "这里是菜单编号为" + id + "所代表的内容";
}

function ClearSubMenu()
{
document.getElementById("divSubMenu").innerHTML = "";
}

</script>
</head>
<body onload="InitHtmlControl()">
<form id="frmDefault" runat="server">
<div>
<table border="0" cellpadding="0" cellspacing="0" style="width: 770px; height: 600px">
<tr>
<td style="width: 20px; height: 25px">
</td>
<td style="width: 730px; height: 25px">
<asp:Label ID="lblShowShowDRMenu" runat="server" Text="下拉菜单例"></asp:Label>
</td>
<td style="width: 20px; height: 25px">
</td>
</tr>
<tr>
<td style="width: 20px; height: 25px">
</td>
<td style="width: 730px; height: 25px">
<div id="divTitleMenu"></div>
</td>
<td style="width: 20px; height: 25px">
</td>
</tr>
<tr>
<td style="width: 20px; height: 25px">
</td>
<td style="width: 730px; height: 25px">
</td>
<td style="width: 20px; height: 25px">
</td>
</tr>
<tr>
<td style="width: 20px; height: 500px">
</td>
<td style="width: 730px; height: 500px;" onclick="ClearSubMenu()">
<div id="divContent"></div>
</td>
<td style="width: 20px; height: 500px">
</td>
</tr>
<tr>
<td style="width: 20px; height: 25px">
</td>
<td style="width: 730px; height: 25px">
</td>
<td style="width: 20px; height: 25px">
</td>
</tr>
</table>
<div id="divSubMenu" style="position:absolute;left:200px;top:190px"></div>

</div>
</form>
</body>
</html>


页面处理类: default.aspx.cs

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using AjaxPro;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
AjaxPro.Utility.RegisterTypeForAjax(typeof(_Default));//注册ajax类
GetMainMenu();
}

/// <summary>
/// 得到主菜单(一级菜单)
/// </summary>
/// <returns>菜单innerHTML形式</returns>
[AjaxPro.AjaxMethod]
public string GetMainMenu()
{
string strOut = "";

CMenu m = new CMenu();

string strConn = " where menu_parentID = 0";//父菜单标记为0的为一级菜单

DataSet ds = new DataSet();

if (m.Query2DB(ref ds, "menu_name,menu_id", strConn))
{
strOut += "<table style=\"width:100%;height:100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">";
strOut += "<tr class=\"tdCaleTitle\">";

int width = 0;

foreach (DataRow row in ds.Tables[0].Rows)
{
strOut += "<td style=\"width:120px\">";
strOut += "<a href=\"javascript:void(0);\" onmousemove=\"GetSubMenu(this," + row["menu_id"] + ")\">"; //调用前台js方法传入当前菜单的编号得到其所有的子菜单
strOut += row["menu_name"];
strOut += "</a>";
strOut += "</td>";
width += 120;
}
if (width > 770)
{
width = 0;
}
else
{
width = 770 - width;
}
strOut += "<td style=\"width:" + width + "px\"></td>";
strOut += "</tr>";
strOut += "</table>";
}

return strOut;
}

[AjaxPro.AjaxMethod]
public string GetSubMenu(long id)
{
string strOut = "";

CMenu m = new CMenu();

string strConn = " where menu_parentID = " + id;//找个此父菜单下所有的子菜单

DataSet ds = new DataSet();

if (m.Query2DB(ref ds, "menu_name,menu_id", strConn))
{
strOut += "<table style=\"width:120px;height:25px\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">";
strOut += "<tr><td style=\"width:120px;height:25px\"></tr>"; //空行的目的是产生与父级菜单的交集
int i = 0;
foreach (DataRow row in ds.Tables[0].Rows)
{
string strCls = "tdCale_Red";
if (0 == i % 2)
{
strCls = "tdCale";
}
strOut += "<tr class=\"" + strCls + "\">";
strOut += "<td style=\"width:120px;height:25px\">";
strOut += "<a href=\"javascript:void(0);\" onclick=\"Go2Conent(" + row["menu_id"] + ")\">"; //调用前台js方法传入当前菜单编号到达此菜单代表的页面
strOut += row["menu_name"];
strOut += "</a>";
strOut += "</td>";
strOut += "</tr>";
i++;
}

strOut += "</table>";
}

return strOut;
}

}

#3
爱像深蓝2007-10-31 21:48
回复:(爱像深蓝)回复:(爱像深蓝)手把手教你做下...

页面实现的效果截图:


注:很多朋友问我半透明菜单如何制作,这里在下先说明做法,使用css的alpha滤镜可以,把opacity的值是透明度的百分比0为完全透明,100不透明.自己试着玩
整个程序源码打包下载,大家可以看下:


只有本站会员才能查看附件,请 登录

#4
shizhusz1102007-11-07 14:48

我学习!不过web太差。。。

#5
yu263131712008-11-24 17:50
yu26313171
1