JavaScript 實現觸點式彈出菜單插件

  以前作項目時常常用到一種觸點式彈出菜單或者導航的功能,這個功能的主要應用場景是:web頁面中多層分級導航或者子功能目錄,但又考慮到頁面區域有限,因而就考慮到在鼠標移動到某導航按鈕上或者點擊時,系統將在該按鈕下浮動一個層,展示子導航或者子目錄,當用戶選擇這些子目錄/導航時,頁面做出相應的操做,這種功能從人機交互和頁面佈局上都有很好的人性化體驗。最近有些閒暇時間,將此功能從新整理並封裝,造成一個公共插件,命名爲:SelectItem.js,分享以下:web

插件的主要實現的功能:數組

  1. 功能模塊化封裝,提供一個對外的初始化接口供應用調用便可,首先須要綁定一個頁面觸發元素(連接/按鈕等),傳入元素id;閉包

  2. 提供子菜單/導航條目的初始化入口,調用方法輸入須要初始化的條目數組,以參數方式輸入; app

  3. 提供對外事件接口,如點擊子菜單/導航的事件定義等,供調用方自定義事件實現;ide

  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值;第三個參數是自定義輔助事件的實現,一樣由調用方定義實現。
this

控件源碼以下:spa

 

  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='width:" + (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='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>"
 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

 

點擊這裏下載源碼

相關文章
相關標籤/搜索