首先申明一点,这个插件不是我写的,是网上一个大神写的,这是他的博客大家可以参考一下:http://www.cnblogs.com/xiangbing/p/mobile-select-area.html
===========================================分割线=========================
在下呢只是就这个插件做了一下简单的适应性改进,需要的朋友可以往下看:
刚开始我也是在网上各种找插件,但是遇到一个问题就是项目要求样式统一,但是各种五花八门的插件样式都不一样,于是索性就找一个插件然后稍作修改,就可以变成功能不同但是样式统一的控件了,废话不多讲,开始:
1、源码+demo |
它的github地址:https://github.com/tianxiangbing/mobile-select-area
它的demo演示:http://www.lovewebgames.com/jsmodule/mobile-select-area.html
2、使用方法 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <!--日期、地址控件 --> <script type="text/javascript" src="dist/jquery-1.12.3.min.js"></script> <link rel="stylesheet" type="text/css" href="dist/mobile-select-date.css"> <link rel="stylesheet" type="text/css" href="dist/dialog.css"> <script type="text/javascript" src="dist/dialog.js"></script> <script type="text/javascript" src="dist/mobile-select-date.js"></script> </head> <body> <div id="txt_date" style="width: 100px;height: 40px;background-color: #ccc;"> </div> <script type="text/javascript"> var selectDate = new MobileSelectDate(); selectDate.init({trigger:‘#txt_date‘}); </script> </body> </html>
/*注释一下:dialog.css和插件js等文件时,如果引入的是压缩版的,那么需要都引入压缩版,如果不是压缩版,那就都引入非压缩版,我也不知道为什么,我试出来的,
还要引入zepto.js或者jquery.js文件*/
3、介绍一下API |
default:0||1
0为空,true时默认选中第一项,默认1
trigger:
触发弹窗的DOM元素 ,可以是input或其他
value:
初始值,
level: int
级别数,默认是3级的
separator: ,
id值分隔符
eventName:tap|click
触发事件名称,默认click,使用zeptojs的可以用tap事件
data:
当data为json对象时可以直接解析,此时直接接收数组
当data为string发送ajax请求后返回json,格式如下:
{ "data": [{ "id": 1, "name": "浙江省", "child": [{ "id": "1", "name": "杭州市", "child": [{ "id": 1, "name": "滨江区" }] }] }, { "id": 2, "name": "江苏省", "child": [{ "id": "1", "name": "南京", "child": [{ "id": 1, "name": "解放区" }] }] }, { "id": 3, "name": "湖北省" }] }
callback:function(scroller,text,value)
第一个是容器,第二个是选中后的text值,第三个参数是选中后的id。 并且this指向当前对象。 选中后的回调,默认有填充trigger的value值,以及赋值它后面紧跟着的hidden的value值,以逗号分隔id,空格分隔文字
4、重点来了,以下是我个人对这个插件的一些修改 |
刚刚大家都应该注意到我上传的代码跟源码有些区别(源码就在文章标题的demo演示地址里)
源码默认的返回值是返回value,但有时候移动端里面需要将触发元素换成其他DOM元素,例如div什么的,但是只有表单元素才有value属性,当时我用这个插件的时候,直接把触发元素换成div,发现返回值无法显示,原因就是这个,div没有value属性,直接上代码,修改后的 mobile-select-date.js
1 ; 2 (function(root, factory) { 3 //amd 4 if (typeof define === ‘function‘ && define.amd) { 5 define([‘$‘], factory); 6 } else if (typeof exports === ‘object‘) { //umd 7 module.exports = factory(); 8 } else { 9 root.MobileSelectDate = factory(window.Zepto || window.jQuery || $); 10 } 11 })(this, function($) { 12 //试图写个傻逼点的代码 13 var MobileSelectDate = function() { 14 var rnd = Math.random().toString().replace(‘.‘, ‘‘); 15 this.id = ‘scroller_‘ + rnd; 16 this.scroller; 17 this.data; 18 this.index = 0; 19 this.value = [0, 0, 0]; 20 this.oldvalue; 21 this.oldtext; 22 this.text = [‘‘, ‘‘, ‘‘]; 23 this.level = 3; 24 this.mtop = 30; 25 this.separator = ‘ ‘; 26 }; 27 MobileSelectDate.prototype = { 28 init: function(settings) { 29 this.settings = $.extend({}, settings); 30 this.separator = "/"; 31 var now = new Date(); 32 this.settings.value = this.settings.value || $(this.settings.trigger).val() || now.getFullYear() + "/" + ("0" + (now.getMonth() + 1)).slice(-2) + ‘/‘ + ("0" + (now.getDate())).slice(-2); 33 this.settings.value = this.settings.value.replace(/\//g, ‘,‘); 34 this.settings.text = this.settings.value.split(‘,‘) 35 this.settings.default==undefined ? this.default=1:this.default = 0 ;//0为空,1时默认选中第一项 36 this.trigger = $(this.settings.trigger); 37 this.trigger.attr("readonly", "readonly"); 38 this.value = (this.settings.value && this.settings.value.split(",")) || [0, 0, 0]; 39 this.text = this.settings.text || this.trigger.val().split(‘ ‘) || [‘‘, ‘‘, ‘‘]; 40 this.oldvalue = this.value.concat([]); 41 this.oldtext = this.text.concat([]); 42 this.min = new Date(this.settings.min || "1900/01/01"); 43 this.settings.max ? this.max = new Date(this.settings.max) : this.max = new Date(); 44 this.getData(); 45 this.bindEvent(); 46 }, 47 //覆盖数据方法,so easy 48 getData: function() { 49 var json = []; 50 for (var s = this.min.getFullYear(), l = this.max.getFullYear(); s <= l; s++) { 51 var obj = {}; 52 obj[‘id‘] = obj[‘name‘] = s; 53 obj.child = []; 54 for (var m = 1; m <= 12; m++) { 55 var o = {}; 56 o[‘id‘] = o[‘name‘] = ("0" + m).slice(-2); 57 o.child = []; 58 var days = new Date(s, m, 0).getDate(); 59 for (var d = 1; d <= days; d++) { 60 var j = {}; 61 j[‘id‘] = j[‘name‘] = ("0" + d).slice(-2); 62 if (!(m == this.max.getMonth() + 1 && s == this.max.getFullYear() && d > this.max.getDate())) { 63 o.child.push(j); 64 } 65 } 66 if (!(m > this.max.getMonth() + 1 && s == this.max.getFullYear())) { 67 obj.child.push(o); 68 } 69 } 70 json.push(obj) 71 } 72 this.data = json; 73 }, 74 bindEvent: function() { 75 var _this = this; 76 this.trigger.click(function(e) { 77 78 var settings,buttons; 79 if( _this.settings.position == "bottom"){ 80 settings ={ 81 position:"bottom", 82 width:"100%", 83 className:"ui-dialog-bottom", 84 animate:false 85 } 86 var buttons=[{ 87 ‘no‘: ‘取消‘ 88 },{ 89 ‘yes‘: ‘确定‘ 90 }]; 91 } 92 93 $.confirm(‘<div class="ui-scroller-mask"><div id="‘ + _this.id + ‘" class="ui-scroller"><div></div><div ></div><div></div><p></p></div></div>‘, buttons, function(t, c) { 94 if (t == "yes") { 95 _this.submit() 96 } 97 if (t == ‘no‘) { 98 _this.cancel(); 99 } 100 this.dispose(); 101 }, $.extend({ 102 width: 320, 103 height: 215 104 },settings)); 105 106 _this.scroller = $(‘#‘ + _this.id); 107 _this.format(); 108 var start = 0, 109 end = 0 110 _this.scroller.children().bind(‘touchstart‘, function(e) { 111 start = (e.changedTouches || e.originalEvent.changedTouches)[0].pageY; 112 }); 113 _this.scroller.children().bind(‘touchmove‘, function(e) { 114 end = (e.changedTouches || e.originalEvent.changedTouches)[0].pageY; 115 var diff = end - start; 116 var dl = $(e.target).parent(); 117 if (dl[0].nodeName != "DL") { 118 return; 119 } 120 var top = parseInt(dl.css(‘top‘) || 0) + diff; 121 dl.css(‘top‘, top); 122 start = end; 123 return false; 124 }); 125 _this.scroller.children().bind(‘touchend‘, function(e) { 126 end = (e.changedTouches || e.originalEvent.changedTouches)[0].pageY; 127 var diff = end - start; 128 var dl = $(e.target).parent(); 129 if (dl[0].nodeName != "DL") { 130 return; 131 } 132 var i = $(dl.parent()).index(); 133 var top = parseInt(dl.css(‘top‘) || 0) + diff; 134 if (top > _this.mtop) { 135 top = _this.mtop; 136 } 137 if (top < -$(dl).height() + 60) { 138 top = -$(dl).height() + 60; 139 } 140 var mod = top / _this.mtop; 141 var mode = Math.round(mod); 142 var index = Math.abs(mode) + 1; 143 if (mode == 1) { 144 index = 0; 145 } 146 _this.value[i] = $(dl.children().get(index)).attr(‘ref‘); 147 _this.value[i] == 0 ? _this.text[i] = "" : _this.text[i] = $(dl.children().get(index)).html(); 148 for (var j = _this.level - 1; j > i; j--) { 149 _this.value[j] = 0; 150 _this.text[j] = ""; 151 } 152 if (!$(dl.children().get(index)).hasClass(‘focus‘)) { 153 _this.format(); 154 } 155 $(dl.children().get(index)).addClass(‘focus‘).siblings().removeClass(‘focus‘); 156 dl.css(‘top‘, mode * _this.mtop); 157 return false; 158 }); 159 return false; 160 }); 161 }, 162 format: function() { 163 var _this = this; 164 var child = _this.scroller.children(); 165 this.f(this.data); 166 }, 167 f: function(data) { 168 var _this = this; 169 var item = data; 170 if (!item) { 171 item = []; 172 }; 173 var str = ‘<dl><dd ref="0">——</dd>‘; 174 var focus = 0, 175 childData, top = _this.mtop; 176 if (_this.index !== 0 && _this.value[_this.index - 1] == "0" && this.default == 0) { 177 str = ‘<dl><dd ref="0" class="focus">——</dd>‘; 178 _this.value[_this.index] = 0; 179 _this.text[_this.index] = ""; 180 focus = 0; 181 } else { 182 if (_this.value[_this.index] == "0") { 183 str = ‘<dl><dd ref="0" class="focus">——</dd>‘; 184 focus = 0; 185 } 186 if (item.length > 0 && this.default == 1) { 187 str = ‘<dl>‘; 188 var pid = item[0].pid || 0; 189 var id = item[0].id || 0; 190 focus = item[0].id; 191 childData = item[0].child; 192 if(!_this.value[this.index ]){ 193 _this.value[this.index ] = id; 194 _this.text[this.index] = item[0].name; 195 } 196 str += ‘<dd pid="‘ + pid + ‘" class="‘ + cls + ‘" ref="‘ + id + ‘">‘ + item[0].name + ‘</dd>‘; 197 } 198 for (var j = _this.default, len = item.length; j < len; j++) { 199 var pid = item[j].pid || 0; 200 var id = item[j].id || 0; 201 var cls = ‘‘; 202 if (_this.value[_this.index] == id) { 203 cls = "focus"; 204 focus = id; 205 childData = item[j].child; 206 top = _this.mtop * (-(j - _this.default)); 207 }; 208 str += ‘<dd pid="‘ + pid + ‘" class="‘ + cls + ‘" ref="‘ + id + ‘">‘ + item[j].name + ‘</dd>‘; 209 } 210 } 211 str += "</dl>"; 212 var newdom = $(str); 213 newdom.css(‘top‘, top); 214 var child = _this.scroller.children(); 215 $(child[_this.index]).html(newdom); 216 _this.index++; 217 if (_this.index > _this.level - 1) { 218 _this.index = 0; 219 return; 220 } 221 _this.f(childData); 222 }, 223 submit: function() { 224 this.oldvalue = this.value.concat([]); 225 this.oldtext = this.text.concat([]); 226 if (this.trigger[0].nodeType == 1) { 227 //input 228 this.trigger.text(this.text.join(this.separator)); 229 this.trigger.attr(‘data-value‘, this.value.join(‘,‘)); 230 } 231 this.trigger.next(‘:hidden‘).val(this.value.join(‘,‘)); 232 this.settings.callback && this.settings.callback(this.scroller); 233 }, 234 cancel: function() { 235 this.value = this.oldvalue.concat([]); 236 this.text = this.oldtext.concat([]); 237 } 238 } 239 return MobileSelectDate; 240 })
大家注意第228行,我把value值改成了text,就这,其实特别简单,但是当时一直没想到改源码就可以实现,费了点时间,
最后,介绍一下这个插件如何拓展为自己的插件 |
这个插件的数据来源就是那个 data.json文件,里面的数据大家可以参考上边介绍的书写格式就可以,然后引入的时候注意一下目录结构关系,