zoukankan      html  css  js  c++  java
  • JavaScript 实现触点式弹出菜单插件

      之前做项目时经常用到一种触点式弹出菜单或者导航的功能,这个功能的主要应用场景是:web页面中多层分级导航或者子功能目录,但又考虑到页面区域有限,于是就考虑到在鼠标移动到某导航按钮上或者点击时,系统将在该按钮下浮动一个层,展现子导航或者子目录,当用户选择这些子目录/导航时,页面作出相应的操作,这种功能从人机交互和页面布局上都有很好的人性化体验。最近有些闲暇时间,将此功能重新整理并封装,形成一个公共插件,命名为:SelectItem.js,分享如下:

    插件的主要实现的功能:

      1. 功能模块化封装,提供一个对外的初始化接口供应用调用即可,首先需要绑定一个页面触发元素(链接/按钮等),传入元素id;

      2. 提供子菜单/导航条目的初始化入口,调用方法输入需要初始化的条目数组,以参数方式输入; 

      3. 提供对外事件接口,如点击子菜单/导航的事件定义等,供调用方自定义事件实现;

      4. 提供辅助添加功能,如果子菜单是选择信息,而初始化的条目又不符合调用需求,则需提供让给调用方自定义条目的功能,此辅助功能可以根据需要进行屏蔽;

    效果图如下:(左侧为带自定义辅助功能的效果,右侧为不带自定义辅助功能的效果)

    上述效果调用时的代码如下:

     1 AutoDiv("btn", false).InitControl([
     2                     {
     3                         key: "12",
     4                         value: "二个选项(A | B)"
     5                     },
     6                     {
     7                         key: "13",
     8                         value: "三个选项(A | B | C)"
     9                     },
    10                     {
    11                         key: "14",
    12                         value: "四个选项(A | B | C | D)"
    13                     },
    14                     {
    15                         key: "15",
    16                         value: "五个选项(A | B | C | D | E)"
    17                     },
    18                     {
    19                         key: "0",
    20                         value: "自定义选项类型"
    21                     }
    22                 ],
    23                 function(value) {
    24                     //处理选中类型
    25                     alert(value);
    26                 },
    27                 function() {
    28                     //打开自定义选项创建窗口
    29                     alert("new dialog.");
    30                 });
    31         }

      可以看出,在页面中引用该js文件,然后对需要触点弹出的页面元素进行插件绑定即可,其中绑定函数AutoDiv("btn", false)有两个参数,第一个参数是需要绑定的页面元素id,第二个参数是个布尔值,需要自定义辅助功能时传递true,否则传递false。绑定好页面元素后,接下来是链式调用过程,函InitControl有三个参数,第一个参数是需要展现的菜单项,它是一个键值对数组(key为选择项的反馈表示,value为菜单项显示信息);第二个参数是菜单项选择点击事件的实现,由调用方定义实现,函数有一个参数,即所选菜单项的key值;第三个参数是自定义辅助事件的实现,同样由调用方定义实现。

    控件源码如下:

      1 /*
      2  *    write by zhangyu,2013-07-09,v1.0
      3  *
      4  *  实现触点式菜单弹出及选择功能
      5  *
      6  */
      7 
      8 function AutoDiv(id, allowNewFlag) {
      9     //预留退路
     10     if (!document.getElementById) return false;
     11     if (!document.createElement) return false;
     12 
     13     //保存当前上下文
     14     var me = this;
     15 
     16     me.targetControlID;         //定义当前绑定的id及其对象
     17     me.targetObj = null;
     18     me.pupDivObj = null;        //定义弹出浮动层对象
     19     me.callBackFun = null;      //选中事件
     20     me.callBackNewFun = null;   //自定义回调事件
     21     me.isFocusIn = false;       //标记浮动层是不是处于鼠标焦点内
     22     me.allowNewFlag = false;    //标记是否显示自定义选项类型选项
     23     me.currentIndex = -1;       //当前选中的结果索引
     24     me.LastIndex = -1;          //上一条选中的结果索引
     25     
     26     me.Result;                  //最后结果‘13’、‘14’、‘15’、‘21’、‘31’
     27 
     28     if (id != null && typeof (id) != undefined && id != "") {
     29         if (!document.getElementById(id)) return false;
     30         //赋值类的成员
     31         me.targetControlID = id;
     32         me.targetObj = document.getElementById(id);
     33     }
     34 
     35     if (allowNewFlag != null && typeof (allowNewFlag) != undefined && allowNewFlag != "") {
     36 
     37         me.allowNewFlag = allowNewFlag;
     38     }
     39 
     40     if (me.pupDivObj == null || typeof (me.pupDivObj) == undefined) {
     41 
     42         me.pupDivObj = document.createElement("div");
     43         me.pupDivObj.setAttribute("class", "pupDiv");
     44         //加载新建的div对象到文档中去
     45         var parent = document.getElementById(me.targetControlID).parentNode;
     46         if (parent != null && typeof (parent) != undefined) {
     47             parent.appendChild(me.pupDivObj);
     48         }
     49     }
     50     //浮动层弹出展现事件
     51     me.pubDiv = function() {
     52         me.pupDivObj.style.display = "block";
     53         me.pupDivObj.style.backgroundColor = "#ffffff";
     54         me.pupDivObj.style.position = "absolute";
     55         me.pupDivObj.style.top = me.targetObj.getBoundingClientRect().top + 20;
     56         me.pupDivObj.style.left = me.targetObj.getBoundingClientRect().left;
     57         me.pupDivObj.style.width = "150";
     58         //绑定内容
     59         me.pupDivObj.innerHTML = me.GetContentTable();
     60         //定义行事件
     61         var result = me.pupDivObj.getElementsByTagName("td");
     62         if (result.length > 0) {
     63             //给每个Td动态绑定事件(新建了一个闭包,用来传递参数,否则所有元素的一下三个鼠标事件的参数i会是相同的值)
     64             for (var i = 0; i < result.length; i++) {
     65                 var bb = new BiBaoOnMouseResult(i, me);
     66                 AddEvent(result[i], "mouseover", bb.OnMouseOverEx);
     67                 AddEvent(result[i], "mouseout", bb.OnMouseOutEx);
     68                 AddEvent(result[i], "click", bb.OnMouseClickEx);
     69             }
     70         }
     71     }
     72     //类型选项绑定函数
     73     me.GetContentTable = function() {
     74         var DivContent = "<table cellSpacing='0' cellPadding='1' align='center' border='0' id='DivContent_Table'>";
     75         for (var i = 0; i < me.itemList.length - 1; i++) {
     76             DivContent += "  <tr ReturnValue='" + me.itemList[i].key + "' name='row'>"
     77                         + "    <td height='15' nowrap>"
     78                         + "      <div style='" + (me.pupDivObj.offsetWidth - 12) + ";' class='listOption' title='" + me.FliterString(me.itemList[i].value) + "'>" + me.FliterString(me.itemList[i].value) + "<div>"
     79                         + "    </td>"
     80                         + "  </tr>";
     81         }
     82         //添加自定义选项
     83         if (me.allowNewFlag) {
     84             DivContent += "  <tr ReturnValue='" + me.itemList[me.itemList.length - 1].key + "' name='line'>"
     85                         + "    <td nowrap>"
     86                         + "      <div style='font-size:1px; border-top:solid 1px #dde0e0; height:3px;'></div>"
     87                         + "    </td>"
     88                         + "  </tr>"
     89                         + "  <tr ReturnValue='" + me.itemList[me.itemList.length - 1].key + "' name='row'>"
     90                         + "    <td height='15' nowrap>"
     91                         + "      <div style='" + (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>"
     92                         + "    </td>"
     93                         + "  </tr>";
     94         }
     95         DivContent += "</table>";
     96         return DivContent;
     97     }
     98     //定义过滤函数
     99     me.FliterString = function(orgString) {
    100         orgString = orgString.replace(new RegExp(""", "gi"), "&#34;");
    101         orgString = orgString.replace(new RegExp("'", "gi"), "&#39;");
    102         return orgString;
    103     }
    104     //绑定触发控件的click事件
    105     AddEvent(me.targetObj, "click", function() {
    106         me.pubDiv();
    107     });
    108     //绑定浮动层的事件
    109     AddEvent(me.pupDivObj, "mouseover", function() {
    110         me.isFocusIn = true;
    111     });
    112     AddEvent(me.pupDivObj, "mouseout", function() {
    113         me.isFocusIn = false;
    114     });
    115     //隐藏弹出层
    116     me.Hide = function() {
    117         me.pupDivObj.style.display = "none";
    118         me.currentIndex = -1;
    119     }
    120     //下拉菜单的鼠标事件
    121     me.OnTdMouseOver = function(i) {
    122         me.currentIndex = i;
    123         var result = me.pupDivObj.firstChild;
    124         result.rows[me.currentIndex].style.cursor = "point";
    125         if (!result || result.rows.length <= 0)
    126             return;
    127         if (result.rows[me.currentIndex] != undefined && result.rows[me.currentIndex].name != "line") {
    128 
    129             //取消之前选中项的颜色
    130             if (result.rows[me.LastIndex] != null) {
    131                 result.rows[me.LastIndex].style.backgroundColor = "#FFFFFF";
    132                 result.rows[me.LastIndex].style.color = "#000000";
    133             }
    134             //改变选中项的颜色
    135             if (result.rows[me.currentIndex] != undefined) {
    136                 result.rows[me.currentIndex].style.backgroundColor = "gray"; //"#3161CE";
    137                 result.rows[me.currentIndex].style.color = "#FFFFFF";
    138             }
    139             me.LastIndex = me.currentIndex;
    140         }
    141     }
    142     me.OnTdMouseOut = function(i) {
    143         var result = me.pupDivObj.firstChild;
    144         if (!result || result.rows.length <= 0)
    145             return;
    146         if (result.rows[me.currentIndex] != undefined && result.rows[me.currentIndex].name != "line") {
    147 
    148             result.rows[me.currentIndex].style.backgroundColor = "#FFFFFF";
    149             result.rows[me.currentIndex].style.color = "#000000";
    150         }
    151     }
    152     me.OnTdMouseClick = function(i) {
    153         var evt = evt || window.event;
    154         var result = me.pupDivObj.firstChild;
    155         if (!result || result.rows.length <= 0)
    156             return;
    157         if (result.rows[me.currentIndex].name != "line") {
    158 
    159             //给输入框赋值
    160             me.Result = result.rows[me.currentIndex].getAttribute("ReturnValue");
    161             //隐藏搜索结果
    162             me.pupDivObj.style.display = "none";
    163             me.currentIndex = -1;
    164             //触发外部事件
    165             if (me.Result == "0") {
    166                 //自定义
    167                 me.callBackNewFun();
    168             }
    169             else {
    170                 me.callBackFun(me.Result);
    171             }
    172         }
    173     }
    174     //绑定控件失去焦点事件
    175     AddEvent(me.targetObj, "blur", function() {
    176         if (!me.isFocusIn) {
    177             me.Hide();
    178         }
    179     });
    180     //初始化事件函数
    181     me.InitControl = function(itemList, callBackFun, callBackNewFun) {
    182         //需要绑定的选项
    183         if (itemList.length > 0) {
    184             me.itemList = itemList;
    185         }
    186         else { me.itemList = []; }
    187         //初始化选项的点击函数
    188         if (me.callBackFun == null || typeof (me.callBackFun) == undefined) {
    189             me.callBackFun = callBackFun;
    190         }
    191         //初始化新建选项的点击函数
    192         if (me.callBackNewFun == null || typeof (me.callBackNewFun) == undefined) {
    193             me.callBackNewFun = callBackNewFun;
    194         }
    195     }
    196     //添加对象事件
    197     function AddEvent(target, eventType, callback) {
    198         DeleteEvent(target, eventType, callback);
    199         if (target.addEventListener) {
    200             target.addEventListener(eventType, callback, false);
    201         }
    202         else {
    203             //ie
    204             target.attachEvent("on" + eventType, function(event) { return callback.call(target, event); });
    205         }
    206     }
    207     //删除对象事件
    208     function DeleteEvent(target, eventType, callback) {
    209         if (target.removeEventListener) {
    210             target.removeEventListener(eventType, callback, true);
    211         }
    212         else {
    213             //ie
    214             target.detachEvent("on" + eventType, callback);
    215         }
    216     }
    217     //返回对象
    218     return me;
    219 };
    220 /*
    221 * 新建一个闭包,用于实现鼠标点击搜索结果时的事件,以解决通过训练传递的参数一直是最后一个索引的问题    
    222 *
    223 * writter:zhangyu 2012-01-03
    224 */
    225 function BiBaoOnMouseResult(i, me) {
    226     this.OnMouseClickEx = function() {
    227         me.OnTdMouseClick(i);
    228     };
    229     this.OnMouseOverEx = function() {
    230         me.OnTdMouseOver(i);
    231     };
    232     this.OnMouseOutEx = function() {
    233         me.OnTdMouseOut(i);
    234     };
    235 }
    View Code

    点击这里下载源码

  • 相关阅读:
    如何组建开发团队-建立畅通的沟通渠道
    如何组建开发团队-激励团队气势
    文件夹名与类名一致造成的命名空间无法识别的问题
    SQL Server 还原错误“restore database正在异常终止 错误 3154”
    S​Q​L​ ​S​e​r​v​e​r​ ​服务无法启动,错误1069解决办法
    无法升级数据库....因为此版本的 SQL Server 不支持该数据库的非发布版本(539) 解决方案
    图解Microsoft SQL Server——“远程过程调用失败 [0x800706be] 错误“。
    Eclipse: Android Device Chooser
    部署网站时的错误“one of its dependencies.试图加载格式不正确的程序。”解决方案。
    把char赋值到string里面
  • 原文地址:https://www.cnblogs.com/freshfish/p/3482493.html
Copyright © 2011-2022 走看看