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

    点击这里下载源码

  • 相关阅读:
    HDU 6182 A Math Problem 水题
    HDU 6186 CS Course 位运算 思维
    HDU 6188 Duizi and Shunzi 贪心 思维
    HDU 2824 The Euler function 欧拉函数
    HDU 3037 Saving Beans 多重集合的结合 lucas定理
    HDU 3923 Invoker Polya定理
    FZU 2282 Wand 组合数学 错排公式
    HDU 1452 Happy 2004 数论
    HDU 5778 abs 数论
    欧拉回路【判断连通+度数为偶】
  • 原文地址:https://www.cnblogs.com/freshfish/p/3482493.html
Copyright © 2011-2022 走看看