前言
很久没有写博客了,话说真的工作后才发现很多需要学的,有很多不足。
加之最近工作没有什么沉淀,现在团队又面临解散,反正闲着也是闲着,就自己写了个插件,反正水平就这样,当时自我总结吧!
应用背景
在我们工作中,经常会遇到这种需求:
① 鼠标点击某个文本框时出现下拉菜单
② 常用的操作鼠标划上出现下拉菜单
③ 按钮类应用
我们会用到这种功能往往原因是因为地方小了,按钮多了,这往往说明产品设计一般出问题了。。。 但是,我辈屁民豪不关注产品(没资格插手),所以需要完成以上功能;
其实总的来说,这些功能还是非常实用的。
于是,为了应对以上场景,我工作中先是做了一个,然后又遇到了,然后又遇到了,所以最后就写了这么一个东西。
集中展示
几个功能放到一起了,前端代码如下:
View Code
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 2 <html xmlns="http://www.w3.org/1999/xhtml"> 3 <head> 4 <title></title> 5 <style type="text/css"> 6 body{ font: 12px/1.231 tahoma,arial,宋体; } 7 .drop_list_items , .drop_list_items ul { display: none; position:absolute; background-color: #FFFFFF; border: 1px solid #D2D2D2; padding: 2px; margin: 0; } 8 .drop_list_items li { margin: 0; padding: 4px; list-style: none; cursor: pointer; } 9 .drop_list_items li:hover { background-color: #3399FF; }10 .drop_list_items li.parent_drop_list { padding: 4px; list-style: none; }11 .drop_list_items li.cur_active { background-color: #3399FF; }12 .z800 { z-index: 800; } 13 </style>14 <script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="http://www.cnblogs.com/jquery-1.7.1.min.js"></script>15 <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="DropList.js" type="text/javascript"></script>16 <script type="text/javascript">17 18 //方案一19 $(document).ready(function () {20 new DropList({21 id: 'click_btn_drop',22 dropItems: [23 ['短信选定用户', 'select'],24 ['短信全部用户', 'all'],25 ['短信未发送用户用户', 'all_else']26 ],27 func: function (e, scope, listEl) {28 var el = $(this);29 alert(el.html());30 scope.closeList();31 var s = '';32 }33 });34 35 new DropList({36 id: 'div1',37 open: '1',38 close: '1',39 dropItems: [40 ['昵称'],41 ['姓名'],42 ['性别'],43 ['联系方式']44 ],45 func: function (e, scope, listEl, toggleEl) {46 var el = $(this);47 scope.closeList();48 toggleEl.val(el.html());49 }50 });51 52 new DropList({53 id: 'click_text_drop',54 dropItems: [55 ['昵称'],56 ['姓名'],57 ['性别'],58 ['联系方式']59 ],60 func: function (e, scope, listEl, toggleEl) {61 var el = $(this);62 scope.closeList();63 toggleEl.val(el.html());64 }65 });66 67 });68 </script>69 </head>70 <body>71 72 73 <div id="click_btn_drop" style=" width:140px;" >74 点击按钮出现下拉菜单75 </div>76 <br />77 <br />78 79 80 <input id="click_text_drop" type="text" />81 <br />82 <br />83 <div id="div1" style=" width:140px;" >84 鼠标滑动85 </div>86 87 </body>88 </html>
js代码:
View Code
var DropList = function (opts) { if (!opts.id) { alert('请指定触发展开事件的元素id'); return false; } //触发展开元素id this.toggleId = opts.id; this.toggleEl = opts.id ? $('#' + opts.id) : $('body'); this.key = opts.id ? opts.id + '_list' : new Date().getTime(); this.open = opts.open || 'click'; //展开菜单方式 mousein this.close = opts.close || 'click'; //关闭菜单方式 mouseleave //this.initShow = false; //判断是否初始化出现菜单绑定事件 /*下拉菜单数据,可能出现多级菜单数据格式: [['v', 'k', []], ['v', {}, []], ['v', 'k', [['v', 'k', []], ['v', 'k', []]] ] */ this.dropItems = opts.dropItems || null; this.loadData = opts.loadData; //用于异步加载下拉菜单数据//具有层级关系 this.listEl = null; this.func = opts.func || null; //点击时的事件处理 //同步方式加载 if (this.dropItems) { this.initDropItems(); this.eventBind(); } else { }};DropList.prototype.closeList = {};DropList.prototype.dropItemLoad = function (data, el) { for (var i in data) { var item = data[i]; var tmp = $('<li></li>'); el.append(tmp); //标签已装载 if (item[0]) { tmp.html(item[0]); } if (item[1] || typeof item[1] == 'number') { if (typeof item[1] == 'string' || typeof item[1] == 'number') { tmp.attr('id', item[1]); } else { for (_k in item[1]) { tmp.attr(_k, item[1][_k]); } } } if (item[2] && item[2]['length']) {//此处需要递归 var child = $('<ul ></ul>') tmp.append(child); tmp.addClass('parent_drop_list'); this.dropItemLoad(item[2], child); } }};//['v', 'k', []]DropList.prototype.initDropItems = function () { var scope = this; var dropItems = scope.dropItems; var listEl = $('<ul class="drop_list_items" id="' + scope.key + '"></ul>'); $('body').append(listEl); scope.dropItemLoad(dropItems, listEl); scope.listEl = listEl;};DropList.prototype.closeList = function () { var listEl = this.listEl; listEl.find('li').removeClass('cur_active'); listEl.find('ul').hide(); listEl.hide();};DropList.prototype.eventBind = function () { var scope = this; var listEl = scope.listEl; var toggleEl = scope.toggleEl; var open = scope.open; var close = scope.close; var func = scope.func; var obj_len = function (o) { var len = 0; for (var k in o) { len++; } return len; }; var func_cls = function () { if (close == 'click') { $(document).click(function (e) { var el = $(e.target); var is_el = false; //判断父元素是否为 while (el.attr('id') != scope.key) { if (el.is("ul") || el.is('li')) { is_el = true; el = el.parent(); } else { break; } } if (el.attr('id') == scope.toggleId) { is_el = true; } if (!is_el) { scope.closeList(); if (scope.closeList[scope.toggleId]) delete scope.closeList[scope.toggleId]; if (obj_len(scope.closeList) == 0) $(document).unbind('click'); var s = ''; } }); } else { listEl.mouseleave(function (e) { scope.closeList(); if (scope.closeList[scope.toggleId]) delete scope.closeList[scope.toggleId]; listEl.unbind('mouseleave'); }); } }; //确认弹出层位置 var func_init_pos = function (el) { var offset = el.offset(); var h = el.height(); var p_top = el.css('padding-top'); var p_bottom = el.css('padding-bottom'); listEl.css('min-width', (parseInt(el.css('width')) + parseInt(el.css('padding-left')) + parseInt(el.css('padding-right')) - 6) + 'px') listEl.css('left', parseInt(offset.left) + 'px'); listEl.css('top', (parseInt(offset.top) + parseInt(h) + parseInt(p_top) + parseInt(p_bottom)) + 'px'); }; if (open == 'click') { toggleEl.unbind('click').click(function (e) { var el = $(this); var drop_list_items = $('.drop_list_items'); func_init_pos(el); drop_list_items.removeClass('z800'); listEl.addClass('z800'); listEl.show(); func_cls(); scope.closeList[scope.toggleId] = 1; //e.stopPropagation(); //阻止冒泡 }); } else { toggleEl.unbind('mouseenter').mouseenter(function (e) { var el = $(this); var drop_list_items = $('.drop_list_items'); func_init_pos(el); drop_list_items.removeClass('z800'); listEl.addClass('z800'); listEl.show(); func_cls(); //e.stopPropagation(); //阻止冒泡 }); } listEl.delegate('li', 'mouseenter', function (e) { var el = $(this); listEl.find('li').removeClass('cur_active'); listEl.find('ul').hide(); el.addClass('cur_active'); el.children().show(); el = el.parent(); while (el.attr('id') != scope.key) { if (el.is("li")) { el.addClass('cur_active'); } if (el.is('ul')) { el.show(); } el = el.parent(); } e.stopPropagation(); }); if (func && typeof func == 'function') { listEl.delegate('li', 'click', function (e) { func.call(this, e, scope, listEl, toggleEl); e.stopPropagation(); }); }};function initNewDrop(opts) { new DropList(opts);}
难点&后续
做的过程中还是遇到了几个问题的,比如:
① 菜单展开后如何关闭
② 多级菜单如何处理
不完善的级联效果
③ 事件如何回调
最后做出了这个比较简陋的东东。。。。
但是做完后也发现了一些问题:
① 像这种菜单在最左最下出现时没有解决;
② 然后菜单项过多时候也没有出现像select的滚动条;
③ 由于个人水平,整个代码的质量亦有问题;
④ 开始也考虑了异步数据加载的问题,但是着实有点难便放弃了,功能代码有一点,有兴趣的同学可以看看:
View Code
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 2 <html xmlns="http://www.w3.org/1999/xhtml"> 3 <head> 4 <title></title> 5 <style type="text/css"> 6 * 7 { 8 margin:0; 9 } 10 body 11 { 12 font: 12px/1.231 tahoma,arial,宋体; 13 } 14 div 15 { 16 width:160px; 17 margin:5px; 18 } 19 20 .drop_btn ul 21 { 22 position:absolute; 23 background-color: #FFFFFF; 24 border: 1px solid #D2D2D2; 25 padding: 2px; 26 line-height: 18px; 27 display: none; 28 top: 25px; 29 z-index: 500; 30 31 } 32 33 .drop_btn li 34 { 35 list-style: none; 36 } 37 .drop_btn_toggle 38 { 39 background: url("http://shz.qq.com/statics/images/button.png") repeat-x scroll 0 0 #E5E5E5; 40 border: 1px solid #999999; 41 box-shadow: 0 1px 0 #E5E5E5; 42 border-radius: 3px; 43 cursor: pointer; 44 height: 28px; 45 line-height: 28px; 46 *height: 18px; 47 *line-height: 18px; 48 padding: 3px 6px; 49 vertical-align: middle; 50 zoom:1; 51 } 52 .drop_btn_open .drop_btn_toggle 53 { 54 background: url("http://shz.qq.com/statics/images/button_selected.png") repeat-x scroll 0 0 #B4B4B4; 55 border-color: #CCCCCC #B1B1B1 #AFAFAF #BEBEBE; 56 color: #515151; 57 } 58 .drop_btn_toggle .icon 59 { 60 border-left: 4px dashed transparent; 61 border-right: 4px dashed transparent; 62 border-top: 4px solid; 63 display: inline-block; 64 width: 0; 65 height: 0; 66 margin: 11px 0 0 4px; 67 *margin: 6px 0 0 4px; 68 overflow: hidden; 69 vertical-align: top; 70 } 71 72 div.drop_btn_open ul 73 { 74 display: block; 75 } 76 .drop_btn li 77 { 78 padding: 2px; 79 cursor: pointer; 80 } 81 .drop_btn li:hover 82 { 83 background-color: #3399FF; 84 } 85 </style> 86 <script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="http://www.cnblogs.com/jquery-1.7.1.min.js"></script> 87 <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="DropList.js" type="text/javascript"></script> 88 <script type="text/javascript"> 89 90 //方案一 91 $(document).ready(function () { 92 var click = new DropList({ 93 id: 'click_btn_drop', 94 toggleText: '给用户发送短信', 95 openType: 'move', 96 drop_items: [ 97 { id: 'select', text: '短信选定用户' }, 98 { id: 'all', text: '短信全部用户' }, 99 { id: 'all_else', text: '短信未发送用户用户' }100 ],101 func: function (e, container) {102 var el = $(this);103 alert(el.html())104 var s = '';105 }106 });107 108 var move = new DropList({109 id: 'move_btn_drop',110 toggleText: '给用户发送短信',111 112 loadData: function (callBack) {113 var scope = this;114 $.get('Handler.ashx', function (data) {115 if (data && typeof data == 'string') {116 data = eval('(' + data + ')');117 }118 data = data.data;119 var param = [];120 param.push({ text: '报名人数:' + data.reg_num });121 var type = data.notice;122 if (type == 0) {123 msg = '不发送短信';124 } else if (type == 1) {125 msg = '自动短信';126 } else if (type == 3) {127 msg = '手动短信';128 }129 param.push({ text: '短信类型:' + msg });130 param.push({ text: '<a href="#">自动短信条数:' + data.sms_auto_count + '</a>'});131 param.push({ text: '<a , function (e) {402 func.call(this, e, container, toggleEl);403 });404 }405 };
所以先贴出来和各位看看,后续小生再行优化,希望能把这个功能做好!
點擊查看更多內容
為 TA 點贊
評論
評論
共同學習,寫下你的評論
評論加載中...
作者其他優質文章
正在加載中
感謝您的支持,我會繼續努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦