JavaScript 实现触点式弹出菜单插件
2013-12-19 19:20
597 查看
之前做项目时经常用到一种触点式弹出菜单或者导航的功能,这个功能的主要应用场景是:web页面中多层分级导航或者子功能目录,但又考虑到页面区域有限,于是就考虑到在鼠标移动到某导航按钮上或者点击时,系统将在该按钮下浮动一个层,展现子导航或者子目录,当用户选择这些子目录/导航时,页面作出相应的操作,这种功能从人机交互和页面布局上都有很好的人性化体验。最近有些闲暇时间,将此功能重新整理并封装,形成一个公共插件,命名为:SelectItem.js,分享如下:
插件的主要实现的功能:
1. 功能模块化封装,提供一个对外的初始化接口供应用调用即可,首先需要绑定一个页面触发元素(链接/按钮等),传入元素id;
2. 提供子菜单/导航条目的初始化入口,调用方法输入需要初始化的条目数组,以参数方式输入;
3. 提供对外事件接口,如点击子菜单/导航的事件定义等,供调用方自定义事件实现;
4. 提供辅助添加功能,如果子菜单是选择信息,而初始化的条目又不符合调用需求,则需提供让给调用方自定义条目的功能,此辅助功能可以根据需要进行屏蔽;
效果图如下:(左侧为带自定义辅助功能的效果,右侧为不带自定义辅助功能的效果)
View Code
点击这里下载源码
插件的主要实现的功能:
1. 功能模块化封装,提供一个对外的初始化接口供应用调用即可,首先需要绑定一个页面触发元素(链接/按钮等),传入元素id;
2. 提供子菜单/导航条目的初始化入口,调用方法输入需要初始化的条目数组,以参数方式输入;
3. 提供对外事件接口,如点击子菜单/导航的事件定义等,供调用方自定义事件实现;
4. 提供辅助添加功能,如果子菜单是选择信息,而初始化的条目又不符合调用需求,则需提供让给调用方自定义条目的功能,此辅助功能可以根据需要进行屏蔽;
效果图如下:(左侧为带自定义辅助功能的效果,右侧为不带自定义辅助功能的效果)
/* * write by zhangyu,2013-07-09,v1.0 * * 实现触点式菜单弹出及选择功能 * */ function AutoDiv(id, allowNewFlag) { //预留退路 if (!document.getElementById) return false; if (!document.createElement) return false; //保存当前上下文 var me = this; me.targetControlID; //定义当前绑定的id及其对象 me.targetObj = null; me.pupDivObj = null; //定义弹出浮动层对象 me.callBackFun = null; //选中事件 me.callBackNewFun = null; //自定义回调事件 me.isFocusIn = false; //标记浮动层是不是处于鼠标焦点内 me.allowNewFlag = false; //标记是否显示自定义选项类型选项 me.currentIndex = -1; //当前选中的结果索引 me.LastIndex = -1; //上一条选中的结果索引 me.Result; //最后结果‘13’、‘14’、‘15’、‘21’、‘31’ if (id != null && typeof (id) != undefined && id != "") { if (!document.getElementById(id)) return false; //赋值类的成员 me.targetControlID = id; me.targetObj = document.getElementById(id); } if (allowNewFlag != null && typeof (allowNewFlag) != undefined && allowNewFlag != "") { me.allowNewFlag = allowNewFlag; } if (me.pupDivObj == null || typeof (me.pupDivObj) == undefined) { me.pupDivObj = document.createElement("div"); me.pupDivObj.setAttribute("class", "pupDiv"); //加载新建的div对象到文档中去 var parent = document.getElementById(me.targetControlID).parentNode; if (parent != null && typeof (parent) != undefined) { parent.appendChild(me.pupDivObj); } } //浮动层弹出展现事件 me.pubDiv = function() { me.pupDivObj.style.display = "block"; me.pupDivObj.style.backgroundColor = "#ffffff"; me.pupDivObj.style.position = "absolute"; me.pupDivObj.style.top = me.targetObj.getBoundingClientRect().top + 20; me.pupDivObj.style.left = me.targetObj.getBoundingClientRect().left; me.pupDivObj.style.width = "150"; //绑定内容 me.pupDivObj.innerHTML = me.GetContentTable(); //定义行事件 var result = me.pupDivObj.getElementsByTagName("td"); if (result.length > 0) { //给每个Td动态绑定事件(新建了一个闭包,用来传递参数,否则所有元素的一下三个鼠标事件的参数i会是相同的值) for (var i = 0; i < result.length; i++) { var bb = new BiBaoOnMouseResult(i, me); AddEvent(result[i], "mouseover", bb.OnMouseOverEx); AddEvent(result[i], "mouseout", bb.OnMouseOutEx); AddEvent(result[i], "click", bb.OnMouseClickEx); } } } //类型选项绑定函数 me.GetContentTable = function() { var DivContent = "<table cellSpacing='0' cellPadding='1' align='center' border='0' id='DivContent_Table'>"; for (var i = 0; i < me.itemList.length - 1; i++) { DivContent += " <tr ReturnValue='" + me.itemList[i].key + "' name='row'>" + " <td height='15' nowrap>" + " <div style='width:" + (me.pupDivObj.offsetWidth - 12) + ";' class='listOption' title='" + me.FliterString(me.itemList[i].value) + "'>" + me.FliterString(me.itemList[i].value) + "<div>" + " </td>" + " </tr>"; } //添加自定义选项 if (me.allowNewFlag) { DivContent += " <tr ReturnValue='" + me.itemList[me.itemList.length - 1].key + "' name='line'>" + " <td nowrap>" + " <div style='font-size:1px; border-top:solid 1px #dde0e0; height:3px;'></div>" + " </td>" + " </tr>" + " <tr ReturnValue='" + me.itemList[me.itemList.length - 1].key + "' name='row'>" + " <td height='15' nowrap>" + " <div style='width:" + (me.pupDivObj.offsetWidth - 12) + ";' class='listOption' title='" + me.FliterString(me.itemList[me.itemList.length - 1].value) + "'>" + me.FliterString(me.itemList[me.itemList.length - 1].value) + "<div>" + " </td>" + " </tr>"; } DivContent += "</table>"; return DivContent; } //定义过滤函数 me.FliterString = function(orgString) { orgString = orgString.replace(new RegExp("\"", "gi"), """); orgString = orgString.replace(new RegExp("'", "gi"), "'"); return orgString; } //绑定触发控件的click事件 AddEvent(me.targetObj, "click", function() { me.pubDiv(); }); //绑定浮动层的事件 AddEvent(me.pupDivObj, "mouseover", function() { me.isFocusIn = true; }); AddEvent(me.pupDivObj, "mouseout", function() { me.isFocusIn = false; }); //隐藏弹出层 me.Hide = function() { me.pupDivObj.style.display = "none"; me.currentIndex = -1; } //下拉菜单的鼠标事件 me.OnTdMouseOver = function(i) { me.currentIndex = i; var result = me.pupDivObj.firstChild; result.rows[me.currentIndex].style.cursor = "point"; if (!result || result.rows.length <= 0) return; if (result.rows[me.currentIndex] != undefined && result.rows[me.currentIndex].name != "line") { //取消之前选中项的颜色 if (result.rows[me.LastIndex] != null) { result.rows[me.LastIndex].style.backgroundColor = "#FFFFFF"; result.rows[me.LastIndex].style.color = "#000000"; } //改变选中项的颜色 if (result.rows[me.currentIndex] != undefined) { result.rows[me.currentIndex].style.backgroundColor = "gray"; //"#3161CE"; result.rows[me.currentIndex].style.color = "#FFFFFF"; } me.LastIndex = me.currentIndex; } } me.OnTdMouseOut = function(i) { var result = me.pupDivObj.firstChild; if (!result || result.rows.length <= 0) return; if (result.rows[me.currentIndex] != undefined && result.rows[me.currentIndex].name != "line") { result.rows[me.currentIndex].style.backgroundColor = "#FFFFFF"; result.rows[me.currentIndex].style.color = "#000000"; } } me.OnTdMouseClick = function(i) { var evt = evt || window.event; var result = me.pupDivObj.firstChild; if (!result || result.rows.length <= 0) return; if (result.rows[me.currentIndex].name != "line") { //给输入框赋值 me.Result = result.rows[me.currentIndex].getAttribute("ReturnValue"); //隐藏搜索结果 me.pupDivObj.style.display = "none"; me.currentIndex = -1; //触发外部事件 if (me.Result == "0") { //自定义 me.callBackNewFun(); } else { me.callBackFun(me.Result); } } } //绑定控件失去焦点事件 AddEvent(me.targetObj, "blur", function() { if (!me.isFocusIn) { me.Hide(); } }); //初始化事件函数 me.InitControl = function(itemList, callBackFun, callBackNewFun) { //需要绑定的选项 if (itemList.length > 0) { me.itemList = itemList; } else { me.itemList = []; } //初始化选项的点击函数 if (me.callBackFun == null || typeof (me.callBackFun) == undefined) { me.callBackFun = callBackFun; } //初始化新建选项的点击函数 if (me.callBackNewFun == null || typeof (me.callBackNewFun) == undefined) { me.callBackNewFun = callBackNewFun; } } //添加对象事件 function AddEvent(target, eventType, callback) { DeleteEvent(target, eventType, callback); if (target.addEventListener) { target.addEventListener(eventType, callback, false); } else { //ie target.attachEvent("on" + eventType, function(event) { return callback.call(target, event); }); } } //删除对象事件 function DeleteEvent(target, eventType, callback) { if (target.removeEventListener) { target.removeEventListener(eventType, callback, true); } else { //ie target.detachEvent("on" + eventType, callback); } } //返回对象 return me; }; /* * 新建一个闭包,用于实现鼠标点击搜索结果时的事件,以解决通过训练传递的参数一直是最后一个索引的问题 * * writter:zhangyu 2012-01-03 */ function BiBaoOnMouseResult(i, me) { this.OnMouseClickEx = function() { me.OnTdMouseClick(i); }; this.OnMouseOverEx = function() { me.OnTdMouseOver(i); }; this.OnMouseOutEx = function() { me.OnTdMouseOut(i); }; }
View Code
点击这里下载源码
相关文章推荐
- javascript之六种数据类型以及特殊注意点
- 分享一个介绍8款js框架比较的链接
- [译] 第八天: Harp.JS - 新型静态Web服务器
- JS 同步执行
- JSTL对Map集合的操作
- 深入理解 js 闭包
- js 判断字符长度
- extJs:triggerAction,typeAhead,typeAheadDelay 意思 解释
- JSP页面倒计时
- javascript 设计模式 读书笔记 封装和信息隐藏
- js获取select选中的option的text示例代码
- JS 写的 HTML解析,获取文本内容
- JS获取当前日期是开学后的第几周,星期几
- JSP中获取当天日期
- 在一个js文件中引入另一个js文件
- Jsoup(1.7.3)学习笔记
- JSP系列五:JSP隐含对象收藏
- jsp的八个隐含对象1
- arcgis api for javascript中使用proxy.jsp
- 无废话ExtJs 入门教程