仿iphone日历插件(beta)

前言

小伙伴们好,很久不见了。最近工作进入正常期了,所以慢慢的悠闲的时间久没有了,所以不能每天水一篇了。

最近也在听师傅(http://home.cnblogs.com/u/aaronjs/)的教导开始阅读jquery源码了,怎么说呢,阅读的效果其实不是太好。

一来是时间断断续续的没有接上,今天读完明天又忘了,到第三天再读的话,就很多都忘记了;

二来是jquery其实还是有一定难度,加之篇幅也很长,所以读起来还是有一点吃力(我甚至有时候有种想睡的感觉),过了2星期才陆陆续续把core读完,结果很多都无法理解,再加油吧。

反正今年的目标就是把jquery读懂,时间多,不着急了。

时间比较紧未做兼容处理,请使用手机/或者使用chrome开启touch功能查看,后期补上兼容方案,以及修复BUG

关于工作

最近工作上需要在我们的网页上加入一些动画:

① 页面的切入切出的转场动画

② 模仿一个iphone的日历控件

转场动画做的时候其实碰到了很多坑,而且最后做出的效果也一般,因为既有的框架与dom结构已经出来了好久了,改不得,而且就算改了效果也不能保证好,所以暂时放下

这里说的仿iphone日历控件,不如说模仿一个单选框来的实在,而且我这里说是插件,完全就算标题党了,各位可以忽视,所以今日正题吧。

iphone的感觉

第一步我们要找到iphone的感觉,那么iphone是个什么感觉呢:

大概是这么个感觉,但是我做出来却变成了这种感觉,将就着看吧:

总体思路

PS:现在其实正在写功能代码,所以,现在我们是边写边做的,思路乱了各位请包涵

测试代码

这个代码很烂,各位就不要看了,我都不知道怎么写出来的,后面点整理吧,里面的CSS不想写就直接拿别人的用了

  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 /*reset*/
  8 body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td,hr,button,article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{margin:0;padding:0}
  9 body,button,input,select,textarea{font:normal 14px/1.5 Tahoma,"Lucida Grande",Verdana,"Microsoft YaHei",hei;}
 10 article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section,iframe{display:block;}
 11 h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:500;}
 12 address,cite,dfn,em,var,i{font-style:normal;font-weight:normal;font-family:arial;}
 13 ul,ol{list-style:none}
 14 a{color:#000;text-decoration:none}
 15 a:hover{text-decoration:underline;-webkit-transition:color .2s linear;-moz-transition:color .2s linear;-ms-transition:color .2s linear;-o-transition:color .2s linear;transition:color .2s linear;}
 16 fieldset,img,button,input{border:0}
 17 button,input,select,textarea{font-size:100%}
 18 table{border-collapse:collapse;border-spacing:0}
 19 input[type="button"],input[type="submit"]{-webkit-appearance:none;}
 20 body{min-width:320px; background:#f5f5f5;overflow-x:hidden;-webkit-text-size-adjust:none;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-font-smoothing:subpixel-antialiased;-moz-user-select:none;color:#000;}:focus{outline:none;}.clearfix:after{clear:both;content:'.';display:block;height:0;visibility:hidden;line-height:0;}.clearfix{*zoom:1;}.fl{float:left;}.fr{float:right;}.clear{clear:both;}.overflow{overflow:hidden;}.ellips{white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}.ellips_line2,.ellips_line3{display: -webkit-box;-webkit-box-orient: vertical;overflow: hidden;}.ellips_line2{-webkit-line-clamp:2;}.ellips_line3{-webkit-line-clamp:3;}.pos_rel{position:relative;}
 21 html,body,.h100{ height:100%; }
 22 dfn{color:#ff9913; font-size:12px; font-weight:normal;}
 23 /*-----------------------------------------common--------------------*/
 24 .i,.i_bef:before,.i_aft:after,.carlist li:before,.ok_crt:after{background:url(../img/style1/v2_bgs.png) no-repeat; background-size:175px 125px;}
 25 .i_bef:before,.i_aft:after,.carlist li:before{position: absolute;content: "";}
 26 .abs_size{-moz-box-sizing:border-box; -webkit-box-sizing:border-box; box-sizing:border-box;}
 27 .opacity{opacity:0.7; filter:alpha(opacity=70);}
 28 
 29 /*active*/
 30 .list_st_border li:active,.p_hinttxt:active,.search_cancel:active,.citylist dd:active{ background:#f8f8f8;}
 31 .btn_yellow:active{background:#eb840f;}
 32 
 33 /*layout*/
 34 .wrap{margin-top:48px;}
 35 .wrap_pb{margin-top:48px; padding-bottom:45px;}
 36 .p10{padding:10px;}
 37 .hm{text-align:center;}
 38 .break_all{word-break:break-all;}
 39 .fix_b{position:fixed; bottom:0; left:0;z-index:9999;}
 40 
 41 /*font bg color size*/
 42 h1{font:normal 1.286em/1.5 "";}/*18px*/
 43 h2{font:normal 1.143em/1.5 "";}/*16px*/
 44 h3{font:600 1em/1.5 "";}/*14px*/
 45 .price{margin-left:5px;}
 46 .price i{margin-left:2px; font-size:1.286em;}
 47 .greyfont{color:#686868;}
 48 .greyfont1{color:#909090;}
 49 .bggrey{height:100%; background:#f5f5f5;}
 50 
 51 /*header*/
 52 header{position:fixed; top:0; left:0; z-index:9999; width:100%; height:48px;background-color:#1491c5;}
 53 .returnico{position:absolute; left:0; top:0;  width:68px; height:48px; background-color:#15a4d5;}
 54 .returnico:before{left:25px;top:16px;width:12px;height:20px; background-position:0 0;}
 55 .icon_phone,.icon_home{width:42px;height:100%;top:0;position:relative;float:right;}
 56 .icon_phone:before{width:11px;height:20px;top:16px;right:12px;background-position:-115px -65px;}
 57 .icon_home:before{width:20px;height:19px;top:16px;right:10px;background-position:-83px -66px;}
 58 header i:active{opacity:0.7; filter:alpha(opacity=70);}
 59 header h1{position:absolute; width:100%;line-height:48px; text-align:center; letter-spacing:2px; color: #fff;}
 60 .header_r,.header_rs{position:absolute;z-index:9; top:0; right:0; line-height:48px; padding:0 15px; font-size:18px; background:#15a4d5; color:#fff;}
 61 .header_rs{padding:0 5px; font-size:12px; }
 62 
 63 /*background-position*/
 64 .select_n:before{width:20px;height:20px;background-position:-18px 0;}
 65 .select_n.current:before{background-position:-44px 0;}
 66 
 67 /*searchbox*/
 68 .search_wrap{overflow:hidden; padding:10px; background:#dfeaf1;}
 69 .search_box{position:relative; float:left; width:100%;}
 70 .search_input{width:100%; padding:0 10px 0 28px; line-height:30px; background-color:#fff; border-radius:4px; color:#ccc;}
 71 .fdj:before,.fdj:after,.search_box:before,.search_box:after{position:absolute; content:""; z-index:9;}
 72 .fdj:before,.search_box:before{left:5px; top:7px; width:12px; height:12px; border:1px solid #bcbcbc; border-radius:12px;}
 73 .fdj:after,.search_box:after{left:19px; top:17px; width:1px; height:8px; background:#bcbcbc;}
 74 .search_cancel{ display:none;float:left; width:20%; line-height:30px; text-align:center; font-size:16px;color:#1491c5; background:none; border:none;}
 75 .close_icon{display:none; position:absolute; z-index:10; top:8px; right:4px; width:16px; height:16px; border-radius:30px; background:#b1b1b1;}
 76 .close_icon:before,.close_icon:after{position:absolute; content:""; top:4px; left:7px; width:2px; height:8px; background:#fff; }
 77 .close_icon:before{-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg);}
 78 .fdj:after,.search_box:after,.close_icon:after{-webkit-transform:rotate(-45deg);-moz-transform:rotate(-45deg);-ms-transform:rotate(-45deg);-o-transform:rotate(-45deg);transform:rotate(-45deg);}
 79 .search_focus .search_box{width:80%;}
 80 .search_focus .close_icon, .search_focus .search_cancel{display:block;}
 81 .search_input:focus{color:#000;}
 82 
 83 /*tab*/
 84 .tab{ background-color:#f8f8f8; border-bottom:1px solid #dfdfdf;}
 85 .tab li{float:left; width:50%; height:39px; line-height:39px; text-align:center; border-right:1px solid #dfdfdf;}
 86 .tab li:last-child{border-right:none;}
 87 .tab li.tabcrt{ background-color:#dfdfdf;}
 88 
 89 .tab_b{ background-color:#f5f5f5; border-bottom:1px solid #c1c1c1;}
 90 .tab_b li{float:left; width:50%; height:39px; line-height:39px; text-align:center;}
 91 .tab_b li:last-child{border-right:none;}
 92 .tab_b li.tabcrt{color:#1491c5; border-bottom:4px solid #1491c5;}
 93 
 94 /*list*/
 95 .list_st_border{ background:#fff; border-bottom:none; border:1px solid #cfcfcf; }
 96 .list_st_border li{position:relative;padding:0 10px; line-height:42px; border-bottom:1px solid #cfcfcf;}
 97 .list_st_border li:last-child{border-bottom:none;}
 98 
 99 .list_sli{padding:10px; overflow:hidden; border-bottom:1px solid #cfcfcf; background:#fff;}
100 .list_sli .list_sunit{float:left;}
101 
102 .citylist{color:#000;}
103 .citylist dt,.citylist dd{padding-left:10px;border-bottom:1px solid #e2e2e2;}
104 .citylist dt{line-height:25px; background-color:#eaeaea;}
105 .citylist dd{position:relative; font-size:16px; line-height:43px; background-color:#fff;}
106 .citylist .ok_crt{color:#1491c5;}
107 .citylist .ok_crt:after{position:absolute;content:""; right:10px; top:50%; margin-top:-6px; width:12px; height:13px; background-position:-110px 0;}
108 
109 
110 /*arr*/
111 .li_arr_r{position:relative;}
112 .arr_r{position:absolute;right:0px; top:50%; width:30px; height:30px; margin-top:-15px; }
113 .arr_r:before,.arr_r:after,.li_arr_r:before,.li_arr_r:after{position: absolute; left:15px; content: "";width:2px; height:7px;  background-color:#909090;}
114 .arr_r:before,.li_arr_r:before{top:10px;-webkit-transform:rotate(-45deg); -moz-transform:rotate(-45deg);-ms-transform:rotate(-45deg);-o-transform:rotate(-45deg);transform:rotate(-45deg);}
115 .arr_r:after,.li_arr_r:after{top:15px;-webkit-transform:rotate(45deg); -moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg);}
116 .li_arr_r:before,.li_arr_r:after{left:auto; right:10px; top:50%; margin-top:-5px;}
117 .li_arr_r:after{margin-top:0;}
118 
119 /*p*/
120 .p_grey{margin:10px 5px; font-size:13px; color:#989898;}
121 .p_grey_center{ text-align:center; margin:20px 5px; font-size:13px; color:#989898;}
122 .p_hinttxt{padding:20px 10px; text-align:center; font-size:16px;  color:#1491c5;}
123 
124 
125 /*btn*/
126 .btn_yellow,.btn_del{width:100%; height:44px; line-height:42px; padding:0 10px;  color:#fff;}
127 .btn_yellow{background:#ff9913;}
128 .btn_del{background:#ca4345;text-align:center;font-size:1.2em;}
129 
130 .btn_pay{padding:0 20px;height:44px;float:right;background:#ff7d13;color:#fff;}
131 .btn_pay:active{background:#ff7300;}
132 .room_num {position:absolute; right:10px; width:100px; height:30px; line-height:30px;color:#000;background-color: #fff; text-align:center;border:#bfbfbf 1px solid;}
133 .room_num i{position:absolute; width:30px; height:30px; text-align:center; font:normal 2em/28px "Arial";}
134 .room_num i:first-child{left:0;background:#f4f4f4;color:#d9d9d9;font:normal 2.8em/25px "Arial";}
135 .room_num i:last-child{right:0;background:#06a2d0;color:#fff;}
136 
137 
138     /*日历*/
139 .cui_cldwrap{color:#000;}
140 .cui_cldweek{height:25px; overflow:hidden;font:normal 12px/24px "verdana";border-bottom:1px solid #c8c8c8;}
141 .cui_cldweek li{float:left; width:14%; text-align:center; }
142 .cui_cldweek li:first-child,.cui_cldweek li:last-child{width:15%; color:#acacac;}
143 .cui_cldmonth{height:35px;text-align:center;font:normal 16px/35px "verdana"; background:#fff;}
144 .cui_cldunit{margin-bottom:20px;}
145 .cui_cld_daybox{overflow:hidden; background:#fff;}
146 .cui_cld_daybox li{float:left; width:14%; height:45px; padding:4px 0; font:normal 12px/45px "verdana"; overflow:hidden; text-align:center;}
147 .cui_cld_daybox li:nth-child(7n),.cui_cld_daybox li:nth-child(7n+1){width:15%;}
148 .cui_cld_daypass{ background:#f7f7f7;}
149 .cui_cld_daycrt{background:#06a2d0; color:#fff;}
150 .cui_cld_dayfuture{background:#fff;}
151 .cui_cld_day_nocrtmonth{ visibility:hidden;}
152 .cui_cld_day_havetxt em{display:block; line-height:25px;}
153 .cui_cld_day_havetxt i{display:block;line-height:15px;}
154 .cui_cld_day_hint{color:#06a2d0;}
155 /*全局XXXX*/
156 
157 /*弹出蓝色框*/
158 .cui-pop-box{background:#fff;}
159 .cui-text-center{text-align:center;}
160 .cui-pop-box .cui-hd{height:40px;line-height:40px;font-size:1.2em;color:#fff;background:#1491c5;padding:0 10px;position:relative;}
161 .cui-pop-box .cui-hd .cui-close{position:absolute;top:10px; right:10px; width:18px; height:18px;line-height:18px;border-radius:50%; background:#fff;color:#1491c5;text-align:center;font-weight:bold;}
162 .cui-error{width:150px;margin:auto;border-radius:5px;background:rgba(73,73,73,1);padding:10px;color:#fff;font-weight:700;text-align:center;word-break:break-all;}
163 .cui-select-view li{border-bottom:#dfdfdf 1px solid;padding:.8em 2em .8em .8em;white-space:nowrap; overflow:hidden; text-overflow:ellipsis;position:relative;}
164 .cui-select-view li.current{color:#1084bc;}
165 .cui-select-view li:active{background:rgba(0,0,0,.05);}
166 .cui-select-view li.current:before,.cui-select-view li.current:after{position:absolute;content:"";background:#1084bc;height:3px;top:50%;border-radius:3px;}
167 .cui-select-view li.current:before{width:18px;right:10px;margin-top:-2px;-webkit-transform:rotate(-50deg);-moz-transform:rotate(-50deg);-ms-transform:rotate(-50deg);transform:rotate(-50deg);}
168 .cui-select-view li.current:after{width:9px;right:22px;margin-top:2px;-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg);}
169 
170 .cui-roller{width:100%;height:90px;overflow:hidden;position:relative;display: -webkit-box;display: -moz-box;display: -ms-flexbox;display: -webkit-flex;display: flex;}
171 .cui-roller .ul-list{height:100%;text-align:center;font-size:1.1em;line-height:30px;-webkit-box-flex: 1;-moz-box-flex: 1;-webkit-flex: 1;-ms-flex: 1;flex: 1;}
172 .cui-mask{position:absolute;z-index:3;top: 0;left: 0;width: 100%;height: 100%;pointer-events: none;
173     background: linear-gradient(#fff 0,rgba(245,245,245,0) 52%,rgba(245,245,245,0) 48%,#fff 100%);
174     background: -webkit-gradient(linear,left bottom,left top,from(#fff),color-stop(0.52,rgba(245,245,245,0)),color-stop(0.48,rgba(245,245,245,0)),to(#fff));
175     background: -webkit-linear-gradient(#fff 0,rgba(245,245,245,0) 52%,rgba(245,245,245,0) 48%,#fff 100%);
176     background: -moz-linear-gradient(#fff 0,rgba(245,245,245,0) 52%,rgba(245,245,245,0) 48%,#fff 100%);
177 }
178 .cui-lines{width:100%;height:34px;position:absolute;top:50%;margin-top:-17px;border-top:#dfdfdf 1px solid;border-bottom:#dfdfdf 1px solid;}
179 .cui-roller-tips{color:#8d8d8d;padding:5px;text-align:center;}
180 .cui-roller-btns{background:#f6f5f5;padding:10px;text-align:center;}
181 .cui-roller-btns span{width:45%;display:inline-block;padding:10px 0;color:#fff;}
182 .cui-roller-btns span:active{opacity:.75;}
183 .cui-roller-btns .cui-btns-cancel{background:#a9a9a9;margin-right:5%;}
184 .cui-roller-btns .cui-btns-sure{background:#ff9913;}
185 
186     </style>
187     <script src="../zepto.js" type="text/javascript"></script>
188 </head>
189 
190 <body id="ctripPage" onselectstart="return false">
191 
192 <!--滚轮-->
193 <div class="cui-pop-box">
194      <div class="cui-hd"><div class="cui-text-center">滚轮滚轮滚轮</div></div>
195      <div class="cui-bd">
196               <div class="cui-roller">
197                   <ul class="ul-list" style=" position: absolute;  100%; z-index: 2;  " >
198                       <li>选项1</li>
199                       <li>选项2</li>
200                       <li>选项3</li>
201                       <li>选项4</li>
202                       <li>选项5</li>
203                       <li>选项6</li>
204                       <li>选项7</li>
205                       <li>选项8</li>
206                       <li>选项9</li>
207                       <li>选项10</li>
208                       <li>选项11</li>
209                       <li>选项12</li>
210                       <li>选项13</li>
211                       <li>选项14</li>
212                       <li>选项15</li>
213                       <li>选项16</li>
214                       <li>选项17</li>
215                       <li>选项18</li>
216                       <li>选项19</li>
217                       <li>选项20</li> <li>选项1</li>
218                       <li>选项2</li>
219                       <li>选项3</li>
220                       <li>选项4</li>
221                       <li>选项5</li>
222                       <li>选项6</li>
223                       <li>选项7</li>
224                       <li>选项8</li>
225                       <li>选项9</li>
226                       <li>选项10</li>
227                       <li>选项11</li>
228                       <li>选项12</li>
229                       <li>选项13</li>
230                       <li>选项14</li>
231                       <li>选项15</li>
232                       <li>选项16</li>
233                       <li>选项17</li>
234                       <li>选项18</li>
235                       <li>选项19</li>
236                       <li>选项20</li>
237                   </ul>
238                   
239                   <div class="cui-mask" style=""></div>
240                   <div class="cui-lines">&nbsp;</div>
241               </div> 
242               <p class="cui-roller-tips">提示信息</p>
243               <div class="cui-roller-btns">
244                    <span class="cui-btns-cancel">取消</span><span class="cui-btns-sure">确定</span>
245               </div>
246      </div>
247 </div>
248  
249 
250 <script type="text/javascript">
251 
252     //    var myScroll = new iScroll('wl1');
253 
254 
255 
256 
257     var y1 = 0, y2 = 0;
258     var moveAble = false;
259     var dragEl = null;
260     var parent = $('.cui-roller');
261     var offset;
262     var el_top = 0;
263     var o_top = 0;
264     var t1 = 0, t2 = 0;
265     var timer = null;
266 
267     document.addEventListener("touchstart", touchStart, false);
268     document.addEventListener("touchend", touchEnd, false);
269     document.addEventListener("touchmove", touchMove, false);
270 
271     function touchStart(e) {
272         t1 = e.timeStamp;
273         var srcElement = $(e.srcElement), pos;
274         dragEl = $(e.srcElement).parent();
275         if (dragEl.hasClass('ul-list')) {
276             var pos = getMousePos(e.changedTouches[0]);
277 
278             offset = dragEl.offset();
279             y1 = pos.top - offset.top;
280             var top = parseFloat(dragEl.css('top')) || 0;
281             o_top = top;
282             y1 = y1 - parseFloat(top);
283             moveAble = true;
284         }
285     }
286 
287     function touchMove(e) {
288         if (!dragEl || !moveAble) return false;
289         var pos = getMousePos(e.changedTouches[0]);
290         y2 = pos.top - y1 - offset.top;
291 
292         if (timer) clearTimeout(timer);
293 
294 
295         el_top = y2;
296         dragEl.css('top', y2 + 'px');
297         e.preventDefault();
298     }
299 
300 
301     function touchEnd(e) {
302         t2 = e.timeStamp - t1;
303         var flag = o_top <= el_top ? 1 : -1;
304         var flag2 = el_top > 0 ? 1 : -1;
305 
306         el_top = Math.abs(el_top);
307         var mod = el_top % 30;
308         el_top = (parseInt(el_top / 30) * 30 + (mod > 15 ? 30 : 0)) * flag2;
309         if (t2 >= 200) {
310             dragEl.animate({
311                 top: el_top + 'px'
312             }, 100, 'ease-in-out', function () {
313                 if (el_top > 30) {
314                     dragEl.animate({
315                         top: '30px'
316                     }, 10, 'ease-in-out');
317                 }
318                 if (el_top < 0 && (el_top + dragEl[0].scrollHeight < 60)) {
319                     dragEl.animate({
320                         top: '-' + (dragEl[0].scrollHeight - 60) + 'px'
321                     }, 10, 'ease-in-out');
322                 }
323             });
324         } else {
325             var step = parseInt(t2 / 50);
326             console.log(t2, step);
327 
328             var param = [10, 6, 4, 2];
329             var _tmp = param[step] * 30 * flag;
330             _tmp = el_top + _tmp;
331             dragEl.animate({
332                 top: (_tmp) + 'px'
333             }, 100 + (param[step] * 50), 'ease-in-out', function () {
334                 if (_tmp > 30) {
335                     dragEl.animate({
336                         top: '30px'
337                     }, 10, 'ease-in-out');
338                 }
339                 if (_tmp < 0 && (_tmp + dragEl[0].scrollHeight < 60)) {
340                     dragEl.animate({
341                         top: '-' + (dragEl[0].scrollHeight - 60) + 'px'
342                     }, 10, 'ease-in-out');
343                 }
344             });
345 
346 
347         }
348         moveAble = false;
349     }
350 
351     function getMousePos(event) {
352         var top, left;
353         top = Math.max(document.body.scrollTop, document.documentElement.scrollTop);
354         left = Math.max(document.body.scrollLeft, document.documentElement.scrollLeft);
355         return {
356             top: top + event.clientY,
357             left: left + event.clientX
358         };
359     };
360 
361     var s = '';
362 
363 </script>
364 
365 </body>
366 </html>
View Code

demo请按照图示观看

http://sandbox.runjs.cn/show/dkf9dkwq

关于iscroll

最开始我们总是喜欢找一些已经存在了的解决方案来试试,这样就比较简单了,但是iscroll有一定问题就是他太大了。

最简单的压缩了都快10k了,所以直接给毙了,这里暂时就用不到他了。

zepto的touch事件

我是一个喜欢偷懒的人,我看着zepto有touch事件,本来想拿来直接用用谁知道。。。

  1 //     Zepto.js
  2 //     (c) 2010-2012 Thomas Fuchs
  3 //     Zepto.js may be freely distributed under the MIT license.
  4 
  5 ;(function($){
  6   var touch = {},
  7     touchTimeout, tapTimeout, swipeTimeout,
  8     longTapDelay = 750, longTapTimeout
  9 
 10   function parentIfText(node) {
 11     return 'tagName' in node ? node : node.parentNode
 12   }
 13 
 14   function swipeDirection(x1, x2, y1, y2) {
 15     var xDelta = Math.abs(x1 - x2), yDelta = Math.abs(y1 - y2)
 16     return xDelta >= yDelta ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down')
 17   }
 18 
 19   function longTap() {
 20     longTapTimeout = null
 21     if (touch.last) {
 22       touch.el.trigger('longTap')
 23       touch = {}
 24     }
 25   }
 26 
 27   function cancelLongTap() {
 28     if (longTapTimeout) clearTimeout(longTapTimeout)
 29     longTapTimeout = null
 30   }
 31 
 32   function cancelAll() {
 33     if (touchTimeout) clearTimeout(touchTimeout)
 34     if (tapTimeout) clearTimeout(tapTimeout)
 35     if (swipeTimeout) clearTimeout(swipeTimeout)
 36     if (longTapTimeout) clearTimeout(longTapTimeout)
 37     touchTimeout = tapTimeout = swipeTimeout = longTapTimeout = null
 38     touch = {}
 39   }
 40 
 41   $(document).ready(function(){
 42     var now, delta
 43 
 44     $(document.body)
 45       .bind('touchstart', function(e){
 46         now = Date.now()
 47         delta = now - (touch.last || now)
 48         touch.el = $(parentIfText(e.touches[0].target))
 49         touchTimeout && clearTimeout(touchTimeout)
 50         touch.x1 = e.touches[0].pageX
 51         touch.y1 = e.touches[0].pageY
 52         if (delta > 0 && delta <= 250) touch.isDoubleTap = true
 53         touch.last = now
 54         longTapTimeout = setTimeout(longTap, longTapDelay)
 55       })
 56       .bind('touchmove', function(e){
 57         cancelLongTap()
 58         touch.x2 = e.touches[0].pageX
 59         touch.y2 = e.touches[0].pageY
 60         if (Math.abs(touch.x1 - touch.x2) > 10)
 61           e.preventDefault()
 62       })
 63       .bind('touchend', function(e){
 64          cancelLongTap()
 65 
 66         // swipe
 67         if ((touch.x2 && Math.abs(touch.x1 - touch.x2) > 30) ||
 68             (touch.y2 && Math.abs(touch.y1 - touch.y2) > 30))
 69 
 70           swipeTimeout = setTimeout(function() {
 71             touch.el.trigger('swipe')
 72             touch.el.trigger('swipe' + (swipeDirection(touch.x1, touch.x2, touch.y1, touch.y2)))
 73             touch = {}
 74           }, 0)
 75 
 76         // normal tap
 77         else if ('last' in touch)
 78 
 79           // delay by one tick so we can cancel the 'tap' event if 'scroll' fires
 80           // ('tap' fires before 'scroll')
 81           tapTimeout = setTimeout(function() {
 82 
 83             // trigger universal 'tap' with the option to cancelTouch()
 84             // (cancelTouch cancels processing of single vs double taps for faster 'tap' response)
 85             var event = $.Event('tap')
 86             event.cancelTouch = cancelAll
 87             touch.el.trigger(event)
 88 
 89             // trigger double tap immediately
 90             if (touch.isDoubleTap) {
 91               touch.el.trigger('doubleTap')
 92               touch = {}
 93             }
 94 
 95             // trigger single tap after 250ms of inactivity
 96             else {
 97               touchTimeout = setTimeout(function(){
 98                 touchTimeout = null
 99                 touch.el.trigger('singleTap')
100                 touch = {}
101               }, 250)
102             }
103 
104           }, 0)
105 
106       })
107       .bind('touchcancel', cancelAll)
108 
109     $(window).bind('scroll', cancelAll)
110   })
111 
112   ;['swipe', 'swipeLeft', 'swipeRight', 'swipeUp', 'swipeDown', 'doubleTap', 'tap', 'singleTap', 'longTap'].forEach(function(m){
113     $.fn[m] = function(callback){ return this.bind(m, callback) }
114   })
115 })(Zepto)
View Code

这个就是zepto的touch事件,可以看到他只是对touchend有所监控,会触发一点点事件,所以和我们没有一毛钱关系

在此我便认命的自己敲下了以下代码:

1 document.addEventListener("touchstart", touchStart, false);
2 document.addEventListener("touchend", touchEnd, false);
3 document.addEventListener("touchmove", touchMove, false);

鼠标拖动

该功能的第一个技术点,便是元素跟着鼠标移动,拖到哪里就是哪里,这个大家都比较熟悉了,就不多说

touchend

当拖动结束时,我们要做很多后续的工作:

① 让选项进入既定的轨道

② 是否具有动画效果

③ 动画效果的步长等

PS:开始觉得有几个点可以说说,结果真的写出来却无话可说了,哎。。。。。。

经过以上版本,我们的粗制滥造版便出现了,就是以上的代码。

封装

于是我们就可以在这个基础上整理代码,封装起来了,请看下一步。

整理封装

首先,我们虽然写的不是插件,但是还是应该让他有插件的样子,来点简单的修饰吧。

经过一阶段的休整,我们的代码成了这个样子了:

  1 (function () {
  2     var ScrollRadio = function (opts) {
  3         opts = opts || {};
  4         //容器元素
  5         this.wrapper = opts.wrapper || $(document);
  6         this.body = [
  7             '<div class="cui-roller">',
  8                 '<ul class="ul-list" style=" position: absolute;  100%; z-index: 2;  " >',
  9                 '</ul>',
 10                 '<div class="cui-mask"></div>',
 11                 '<div class="cui-lines">&nbsp;</div>',
 12             '</div>'
 13         ].join('');
 14         this.body = $(this.body);
 15 
 16         //真正拖动的元素(现在是ul)
 17         this.dragEl = this.body.find('.ul-list');
 18         //数据源
 19         this.data = opts.data || [];
 20         this._changed = opts.changed || null;
 21         //当前选项索引
 22         this.selectedIndex = 0;
 23         //当前选项值
 24         this.key = '';
 25         //当前选项显示的值
 26         this.value = '';
 27 
 28         /*
 29         定位实际需要用到的信息
 30         暂时不考虑水平移动吧
 31         */
 32         this.itemHeight = 0; //单个item高度
 33         this.dragHeight = 0; //拖动元素高度
 34         this.dragTop = 0; //拖动元素top
 35         this.animateParam = [10, 8, 7, 6, 6, 6, 5, 5, 4, 2, 0]; //动画参数
 36         this.timeGap = 0; //时间间隔
 37         this.touchTime = 0; //开始时间
 38         this.moveAble = false; //是否正在移动
 39         this.moveState = 'up'; //移动状态,up right down left
 40         this.oTop = 0; //拖动前的top值
 41         this.curTop = 0; //当前容器top
 42         this.mouseY = 0; //鼠标第一次点下时相对父容器的位置
 43 
 44 
 45         this.init();
 46     };
 47     ScrollRadio.prototype = {
 48         constructor: ScrollRadio,
 49         init: function () {
 50             this.initItem();
 51             this.wrapper.append(this.body);
 52             this.initEventParam();
 53             this.bindEvent();
 54 
 55             return this;
 56         },
 57         //增加数据
 58         initItem: function () {
 59             var _tmp, _data, i, k;
 60             for (var i in this.data) {
 61                 _data = this.data[i]
 62                 _tmp = $('<li>' + (_data.val == undefined ? i : _data.val) + '</li>');
 63                 _tmp.attr('data-index', i);
 64                 for (k in _data) {
 65                     _tmp.attr('data-' + k, _data[k]);
 66                 }
 67                 this.dragEl.append(_tmp);
 68             }
 69         },
 70         //初始化事件需要用到的参数信息
 71         initEventParam: function () {
 72             var offset = this.dragEl.offset();
 73             var itemOffset = this.dragEl.find('li').eq(0).offset();
 74             this.itemHeight = itemOffset.height
 75             this.dragTop = offset.top;
 76             this.dragHeight = this.dragEl[0].scrollHeight;
 77             var s = '';
 78         },
 79         bindEvent: function () {
 80             var scope = this;
 81             document.addEventListener("touchstart", function (e) {
 82                 scope.touchStart.call(scope, e);
 83             }, false);
 84             document.addEventListener("touchend", function (e) {
 85                 scope.touchEnd.call(scope, e);
 86             }, false);
 87             document.addEventListener("touchmove", function (e) {
 88                 scope.touchMove.call(scope, e);
 89             }, false);
 90         },
 91         touchStart: function (e) {
 92             //需要判断是否是拉取元素,此处需要递归验证,这里暂时不管
 93             //!!!!!!!!此处不严谨
 94             var el = $(e.srcElement).parent(), pos;
 95             if (el.hasClass('ul-list')) {
 96                 this.touchTime = e.timeStamp;
 97                 //获取鼠标信息
 98                 pos = this.getMousePos(e.changedTouches[0]);
 99                 //注意,此处是相对位置
100                 this.mouseY = pos.top - this.curTop;
101                 this.moveAble = true;
102             }
103         },
104         touchMove: function (e) {
105             if (!this.moveAble) return false;
106             var pos = this.getMousePos(e.changedTouches[0]);
107             //先获取相对容器的位置,在将两个鼠标位置相减
108             this.curTop = pos.top - this.mouseY;
109 
110             this.dragEl.css('top', this.curTop + 'px');
111 
112 
113             e.preventDefault();
114         },
115         touchEnd: function (e) {
116             //时间间隔
117             var scope = this;
118             this.timeGap = e.timeStamp - this.touchTime;
119             var flag = this.oTop <= this.curTop ? 1 : -1; //判断是向上还是向下滚动
120             var flag2 = this.curTop > 0 ? 1 : -1; //这个会影响后面的计算结果
121             this.moveState = flag > 0 ? 'up' : 'down';
122             var ih = parseFloat(this.itemHeight);
123             var ih1 = ih / 2;
124 
125             var top = Math.abs(this.curTop);
126             var mod = top % ih;
127             top = (parseInt(top / ih) * ih + (mod > ih1 ? ih : 0)) * flag2;
128 
129             var step = parseInt(this.timeGap / 10 - 10);
130             step = step > 0 ? step : 0;
131             var speed = this.animateParam[step] || 0;
132             var increment = speed * ih * flag
133             top += increment;
134             this.dragEl.animate({
135                 top: top + 'px'
136             }, 100 + (speed * 20), 'ease-in-out', function () {
137                 if (top > ih) {
138                     scope.dragEl.animate({
139                         top: ih + 'px'
140                     }, 10, 'ease-in-out');
141                 }
142                 if (top < 0 && (top + scope.dragHeight < ih * 2)) {
143                     scope.dragEl.animate({
144                         top: '-' + (scope.dragHeight - ih * 2) + 'px'
145                     }, 10, 'ease-in-out');
146                 }
147             });
148 
149             console.log(this.timeGap, top, increment);
150 
151             this.oTop = top;
152             this.curTop = top;
153             this.moveAble = false;
154 
155         },
156         setKey: function (k) {
157 
158         },
159         setVal: function (v) { },
160         setIndex: function (i) {
161 
162         },
163         getSelected: function () {
164 
165         },
166         getByKey: function (k) { },
167         getByVal: function (v) { },
168         getByIndex: function (i) { },
169 
170         //选项改变时候触发
171         changed: function () {
172 
173         },
174         //获取鼠标信息
175         getMousePos: function (event) {
176             var top, left;
177             top = Math.max(document.body.scrollTop, document.documentElement.scrollTop);
178             left = Math.max(document.body.scrollLeft, document.documentElement.scrollLeft);
179             return {
180                 top: top + event.clientY,
181                 left: left + event.clientX
182             };
183         }
184 
185     };
186 
187 
188     window.ScrollRadio = ScrollRadio;
189 
190 })();
191 
192 var data = [];
193 for (var i = 0; i < 100; i++) {
194     var temp = { val: '选项-' + i };
195     data.push(temp);
196 }
197 
198 
199 
200 var myScroll = new ScrollRadio({
201     wrapper: $('#ctripPage'),
202     data: data
203 });
204 
205    
206 var s = '';
View Code

http://sandbox.runjs.cn/show/biousc1u

其中动画步长可以自己调节,选一个自己认为合适的,下面接着更新。

设置/获取

  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 /*reset*/
  8 body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td,hr,button,article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{margin:0;padding:0}
  9 body,button,input,select,textarea{font:normal 14px/1.5 Tahoma,"Lucida Grande",Verdana,"Microsoft YaHei",hei;}
 10 article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section,iframe{display:block;}
 11 h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:500;}
 12 address,cite,dfn,em,var,i{font-style:normal;font-weight:normal;font-family:arial;}
 13 ul,ol{list-style:none}
 14 a{color:#000;text-decoration:none}
 15 a:hover{text-decoration:underline;-webkit-transition:color .2s linear;-moz-transition:color .2s linear;-ms-transition:color .2s linear;-o-transition:color .2s linear;transition:color .2s linear;}
 16 fieldset,img,button,input{border:0}
 17 button,input,select,textarea{font-size:100%}
 18 table{border-collapse:collapse;border-spacing:0}
 19 input[type="button"],input[type="submit"]{-webkit-appearance:none;}
 20 body{min-width:320px; background:#f5f5f5;overflow-x:hidden;-webkit-text-size-adjust:none;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-font-smoothing:subpixel-antialiased;-moz-user-select:none;color:#000;}:focus{outline:none;}.clearfix:after{clear:both;content:'.';display:block;height:0;visibility:hidden;line-height:0;}.clearfix{*zoom:1;}.fl{float:left;}.fr{float:right;}.clear{clear:both;}.overflow{overflow:hidden;}.ellips{white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}.ellips_line2,.ellips_line3{display: -webkit-box;-webkit-box-orient: vertical;overflow: hidden;}.ellips_line2{-webkit-line-clamp:2;}.ellips_line3{-webkit-line-clamp:3;}.pos_rel{position:relative;}
 21 html,body,.h100{ height:100%; }
 22 dfn{color:#ff9913; font-size:12px; font-weight:normal;}
 23 /*-----------------------------------------common--------------------*/
 24 .i,.i_bef:before,.i_aft:after,.carlist li:before,.ok_crt:after{background:url(../img/style1/v2_bgs.png) no-repeat; background-size:175px 125px;}
 25 .i_bef:before,.i_aft:after,.carlist li:before{position: absolute;content: "";}
 26 .abs_size{-moz-box-sizing:border-box; -webkit-box-sizing:border-box; box-sizing:border-box;}
 27 .opacity{opacity:0.7; filter:alpha(opacity=70);}
 28 
 29 /*active*/
 30 .list_st_border li:active,.p_hinttxt:active,.search_cancel:active,.citylist dd:active{ background:#f8f8f8;}
 31 .btn_yellow:active{background:#eb840f;}
 32 
 33 /*layout*/
 34 .wrap{margin-top:48px;}
 35 .wrap_pb{margin-top:48px; padding-bottom:45px;}
 36 .p10{padding:10px;}
 37 .hm{text-align:center;}
 38 .break_all{word-break:break-all;}
 39 .fix_b{position:fixed; bottom:0; left:0;z-index:9999;}
 40 
 41 /*font bg color size*/
 42 h1{font:normal 1.286em/1.5 "";}/*18px*/
 43 h2{font:normal 1.143em/1.5 "";}/*16px*/
 44 h3{font:600 1em/1.5 "";}/*14px*/
 45 .price{margin-left:5px;}
 46 .price i{margin-left:2px; font-size:1.286em;}
 47 .greyfont{color:#686868;}
 48 .greyfont1{color:#909090;}
 49 .bggrey{height:100%; background:#f5f5f5;}
 50 
 51 /*header*/
 52 header{position:fixed; top:0; left:0; z-index:9999; width:100%; height:48px;background-color:#1491c5;}
 53 .returnico{position:absolute; left:0; top:0;  width:68px; height:48px; background-color:#15a4d5;}
 54 .returnico:before{left:25px;top:16px;width:12px;height:20px; background-position:0 0;}
 55 .icon_phone,.icon_home{width:42px;height:100%;top:0;position:relative;float:right;}
 56 .icon_phone:before{width:11px;height:20px;top:16px;right:12px;background-position:-115px -65px;}
 57 .icon_home:before{width:20px;height:19px;top:16px;right:10px;background-position:-83px -66px;}
 58 header i:active{opacity:0.7; filter:alpha(opacity=70);}
 59 header h1{position:absolute; width:100%;line-height:48px; text-align:center; letter-spacing:2px; color: #fff;}
 60 .header_r,.header_rs{position:absolute;z-index:9; top:0; right:0; line-height:48px; padding:0 15px; font-size:18px; background:#15a4d5; color:#fff;}
 61 .header_rs{padding:0 5px; font-size:12px; }
 62 
 63 /*background-position*/
 64 .select_n:before{width:20px;height:20px;background-position:-18px 0;}
 65 .select_n.current:before{background-position:-44px 0;}
 66 
 67 /*searchbox*/
 68 .search_wrap{overflow:hidden; padding:10px; background:#dfeaf1;}
 69 .search_box{position:relative; float:left; width:100%;}
 70 .search_input{width:100%; padding:0 10px 0 28px; line-height:30px; background-color:#fff; border-radius:4px; color:#ccc;}
 71 .fdj:before,.fdj:after,.search_box:before,.search_box:after{position:absolute; content:""; z-index:9;}
 72 .fdj:before,.search_box:before{left:5px; top:7px; width:12px; height:12px; border:1px solid #bcbcbc; border-radius:12px;}
 73 .fdj:after,.search_box:after{left:19px; top:17px; width:1px; height:8px; background:#bcbcbc;}
 74 .search_cancel{ display:none;float:left; width:20%; line-height:30px; text-align:center; font-size:16px;color:#1491c5; background:none; border:none;}
 75 .close_icon{display:none; position:absolute; z-index:10; top:8px; right:4px; width:16px; height:16px; border-radius:30px; background:#b1b1b1;}
 76 .close_icon:before,.close_icon:after{position:absolute; content:""; top:4px; left:7px; width:2px; height:8px; background:#fff; }
 77 .close_icon:before{-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg);}
 78 .fdj:after,.search_box:after,.close_icon:after{-webkit-transform:rotate(-45deg);-moz-transform:rotate(-45deg);-ms-transform:rotate(-45deg);-o-transform:rotate(-45deg);transform:rotate(-45deg);}
 79 .search_focus .search_box{width:80%;}
 80 .search_focus .close_icon, .search_focus .search_cancel{display:block;}
 81 .search_input:focus{color:#000;}
 82 
 83 /*tab*/
 84 .tab{ background-color:#f8f8f8; border-bottom:1px solid #dfdfdf;}
 85 .tab li{float:left; width:50%; height:39px; line-height:39px; text-align:center; border-right:1px solid #dfdfdf;}
 86 .tab li:last-child{border-right:none;}
 87 .tab li.tabcrt{ background-color:#dfdfdf;}
 88 
 89 .tab_b{ background-color:#f5f5f5; border-bottom:1px solid #c1c1c1;}
 90 .tab_b li{float:left; width:50%; height:39px; line-height:39px; text-align:center;}
 91 .tab_b li:last-child{border-right:none;}
 92 .tab_b li.tabcrt{color:#1491c5; border-bottom:4px solid #1491c5;}
 93 
 94 /*list*/
 95 .list_st_border{ background:#fff; border-bottom:none; border:1px solid #cfcfcf; }
 96 .list_st_border li{position:relative;padding:0 10px; line-height:42px; border-bottom:1px solid #cfcfcf;}
 97 .list_st_border li:last-child{border-bottom:none;}
 98 
 99 .list_sli{padding:10px; overflow:hidden; border-bottom:1px solid #cfcfcf; background:#fff;}
100 .list_sli .list_sunit{float:left;}
101 
102 .citylist{color:#000;}
103 .citylist dt,.citylist dd{padding-left:10px;border-bottom:1px solid #e2e2e2;}
104 .citylist dt{line-height:25px; background-color:#eaeaea;}
105 .citylist dd{position:relative; font-size:16px; line-height:43px; background-color:#fff;}
106 .citylist .ok_crt{color:#1491c5;}
107 .citylist .ok_crt:after{position:absolute;content:""; right:10px; top:50%; margin-top:-6px; width:12px; height:13px; background-position:-110px 0;}
108 
109 
110 /*arr*/
111 .li_arr_r{position:relative;}
112 .arr_r{position:absolute;right:0px; top:50%; width:30px; height:30px; margin-top:-15px; }
113 .arr_r:before,.arr_r:after,.li_arr_r:before,.li_arr_r:after{position: absolute; left:15px; content: "";width:2px; height:7px;  background-color:#909090;}
114 .arr_r:before,.li_arr_r:before{top:10px;-webkit-transform:rotate(-45deg); -moz-transform:rotate(-45deg);-ms-transform:rotate(-45deg);-o-transform:rotate(-45deg);transform:rotate(-45deg);}
115 .arr_r:after,.li_arr_r:after{top:15px;-webkit-transform:rotate(45deg); -moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg);}
116 .li_arr_r:before,.li_arr_r:after{left:auto; right:10px; top:50%; margin-top:-5px;}
117 .li_arr_r:after{margin-top:0;}
118 
119 /*p*/
120 .p_grey{margin:10px 5px; font-size:13px; color:#989898;}
121 .p_grey_center{ text-align:center; margin:20px 5px; font-size:13px; color:#989898;}
122 .p_hinttxt{padding:20px 10px; text-align:center; font-size:16px;  color:#1491c5;}
123 
124 
125 /*btn*/
126 .btn_yellow,.btn_del{width:100%; height:44px; line-height:42px; padding:0 10px;  color:#fff;}
127 .btn_yellow{background:#ff9913;}
128 .btn_del{background:#ca4345;text-align:center;font-size:1.2em;}
129 
130 .btn_pay{padding:0 20px;height:44px;float:right;background:#ff7d13;color:#fff;}
131 .btn_pay:active{background:#ff7300;}
132 .room_num {position:absolute; right:10px; width:100px; height:30px; line-height:30px;color:#000;background-color: #fff; text-align:center;border:#bfbfbf 1px solid;}
133 .room_num i{position:absolute; width:30px; height:30px; text-align:center; font:normal 2em/28px "Arial";}
134 .room_num i:first-child{left:0;background:#f4f4f4;color:#d9d9d9;font:normal 2.8em/25px "Arial";}
135 .room_num i:last-child{right:0;background:#06a2d0;color:#fff;}
136 
137 
138     /*日历*/
139 .cui_cldwrap{color:#000;}
140 .cui_cldweek{height:25px; overflow:hidden;font:normal 12px/24px "verdana";border-bottom:1px solid #c8c8c8;}
141 .cui_cldweek li{float:left; width:14%; text-align:center; }
142 .cui_cldweek li:first-child,.cui_cldweek li:last-child{width:15%; color:#acacac;}
143 .cui_cldmonth{height:35px;text-align:center;font:normal 16px/35px "verdana"; background:#fff;}
144 .cui_cldunit{margin-bottom:20px;}
145 .cui_cld_daybox{overflow:hidden; background:#fff;}
146 .cui_cld_daybox li{float:left; width:14%; height:45px; padding:4px 0; font:normal 12px/45px "verdana"; overflow:hidden; text-align:center;}
147 .cui_cld_daybox li:nth-child(7n),.cui_cld_daybox li:nth-child(7n+1){width:15%;}
148 .cui_cld_daypass{ background:#f7f7f7;}
149 .cui_cld_daycrt{background:#06a2d0; color:#fff;}
150 .cui_cld_dayfuture{background:#fff;}
151 .cui_cld_day_nocrtmonth{ visibility:hidden;}
152 .cui_cld_day_havetxt em{display:block; line-height:25px;}
153 .cui_cld_day_havetxt i{display:block;line-height:15px;}
154 .cui_cld_day_hint{color:#06a2d0;}
155 /*全局XXXX*/
156 
157 /*弹出蓝色框*/
158 .cui-pop-box{background:#fff;}
159 .cui-text-center{text-align:center;}
160 .cui-pop-box .cui-hd{height:40px;line-height:40px;font-size:1.2em;color:#fff;background:#1491c5;padding:0 10px;position:relative;}
161 .cui-pop-box .cui-hd .cui-close{position:absolute;top:10px; right:10px; width:18px; height:18px;line-height:18px;border-radius:50%; background:#fff;color:#1491c5;text-align:center;font-weight:bold;}
162 .cui-error{width:150px;margin:auto;border-radius:5px;background:rgba(73,73,73,1);padding:10px;color:#fff;font-weight:700;text-align:center;word-break:break-all;}
163 .cui-select-view li{border-bottom:#dfdfdf 1px solid;padding:.8em 2em .8em .8em;white-space:nowrap; overflow:hidden; text-overflow:ellipsis;position:relative;}
164 .cui-select-view li.current{color:#1084bc;}
165 .cui-select-view li:active{background:rgba(0,0,0,.05);}
166 .cui-select-view li.current:before,.cui-select-view li.current:after{position:absolute;content:"";background:#1084bc;height:3px;top:50%;border-radius:3px;}
167 .cui-select-view li.current:before{width:18px;right:10px;margin-top:-2px;-webkit-transform:rotate(-50deg);-moz-transform:rotate(-50deg);-ms-transform:rotate(-50deg);transform:rotate(-50deg);}
168 .cui-select-view li.current:after{width:9px;right:22px;margin-top:2px;-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg);}
169 
170 .cui-roller{width:100%;height:90px;overflow:hidden;position:relative;display: -webkit-box;display: -moz-box;display: -ms-flexbox;display: -webkit-flex;display: flex;}
171 .cui-roller .ul-list{height:100%;text-align:center;font-size:1.1em;line-height:30px;-webkit-box-flex: 1;-moz-box-flex: 1;-webkit-flex: 1;-ms-flex: 1;flex: 1;}
172 .cui-mask{position:absolute;z-index:3;top: 0;left: 0;width: 100%;height: 100%;pointer-events: none;
173     background: linear-gradient(#fff 0,rgba(245,245,245,0) 52%,rgba(245,245,245,0) 48%,#fff 100%);
174     background: -webkit-gradient(linear,left bottom,left top,from(#fff),color-stop(0.52,rgba(245,245,245,0)),color-stop(0.48,rgba(245,245,245,0)),to(#fff));
175     background: -webkit-linear-gradient(#fff 0,rgba(245,245,245,0) 52%,rgba(245,245,245,0) 48%,#fff 100%);
176     background: -moz-linear-gradient(#fff 0,rgba(245,245,245,0) 52%,rgba(245,245,245,0) 48%,#fff 100%);
177 }
178 .cui-lines{width:100%;height:34px;position:absolute;top:50%;margin-top:-17px;border-top:#dfdfdf 1px solid;border-bottom:#dfdfdf 1px solid;}
179 .cui-roller-tips{color:#8d8d8d;padding:5px;text-align:center;}
180 .cui-roller-btns{background:#f6f5f5;padding:10px;text-align:center;}
181 .cui-roller-btns span{width:45%;display:inline-block;padding:10px 0;color:#fff;}
182 .cui-roller-btns span:active{opacity:.75;}
183 .cui-roller-btns .cui-btns-cancel{background:#a9a9a9;margin-right:5%;}
184 .cui-roller-btns .cui-btns-sure{background:#ff9913;}
185 
186     </style>
187     
188     <script id="others_zepto_10rc1" type="text/javascript" class="library" src="/js/sandbox/other/zepto.min.js"></script>
189 </head>
190 <body onselectstart="return false">
191     <div class="cui-pop-box">
192         <div class="cui-hd">
193             <div class="cui-text-center">
194                 滚轮滚轮滚轮</div>
195         </div>
196         <div class="cui-bd">
197             <div id="ctripPage">
198             </div>
199             <p class="cui-roller-tips">
200                 提示信息</p>
201             <div class="cui-roller-btns">
202                 <span class="cui-btns-sure" id="set">设置值</span> <span class="cui-btns-sure" id="get">
203                     获取值</span>
204             </div>
205         </div>
206     </div>
207     <script type="text/javascript">
208 
209         //    var myScroll = new iScroll('wl1');
210 
211         (function () {
212             //!!!由于动画原因,获取值可能会出现不准确的情况,比如正在动画却已经取值了
213             //所以设置了一个冷却时间,在冷却时间的情况下设置值等操作不能进行
214             //为了保证唯一性,全部使用index作为索引算了
215             var ScrollRadio = function (opts) {
216                 opts = opts || {};
217                 //容器元素
218                 this.wrapper = opts.wrapper || $(document);
219                 this.body = [
220             '<div class="cui-roller">',
221                 '<ul class="ul-list" style=" position: absolute;  100%; z-index: 2;  " >',
222                 '</ul>',
223                 '<div class="cui-mask"></div>',
224                 '<div class="cui-lines">&nbsp;</div>',
225             '</div>'
226         ].join('');
227                 this.body = $(this.body);
228 
229                 //真正拖动的元素(现在是ul)
230                 this.dragEl = this.body.find('.ul-list');
231                 //数据源
232                 this.data = opts.data || [];
233                 this._changed = opts.changed || null;
234                 //当前选项索引默认选择2项
235                 this.selectedIndex = 1;
236 
237                 //当前选项值
238                 //                this.key = '';
239                 //当前选项显示的值
240                 //                this.value = '';
241 
242                 /*
243                 定位实际需要用到的信息
244                 暂时不考虑水平移动吧
245                 */
246                 this.itemHeight = 0; //单个item高度
247                 this.dragHeight = 0; //拖动元素高度
248                 this.dragTop = 0; //拖动元素top
249                 this.animateParam = [10, 6, 2, 1, 0, 0, 0, 0, 0, 0, 0]; //动画参数
250                 this.timeGap = 0; //时间间隔
251                 this.touchTime = 0; //开始时间
252                 this.moveAble = false; //是否正在移动
253                 this.moveState = 'up'; //移动状态,up right down left
254                 this.oTop = 0; //拖动前的top值
255                 this.curTop = 0; //当前容器top
256                 this.mouseY = 0; //鼠标第一次点下时相对父容器的位置
257                 this.cooling = false; //是否处于冷却时间
258 
259                 this.init();
260             };
261             ScrollRadio.prototype = {
262                 constructor: ScrollRadio,
263                 init: function () {
264                     this.initItem();
265                     this.wrapper.append(this.body);
266                     this.initEventParam();
267                     this.bindEvent();
268 
269                     return this;
270                 },
271                 //增加数据
272                 initItem: function () {
273                     var _tmp, _data, i, k;
274                     for (var i in this.data) {
275                         _data = this.data[i]
276                         _tmp = $('<li>' + (_data.val == undefined ? i : _data.val) + '</li>');
277                         _tmp.attr('data-index', i);
278                         for (k in _data) {
279                             _tmp.attr('data-' + k, _data[k]);
280                         }
281                         this.dragEl.append(_tmp);
282                     }
283                 },
284                 //初始化事件需要用到的参数信息
285                 initEventParam: function () {
286                     var offset = this.dragEl.offset();
287                     var itemOffset = this.dragEl.find('li').eq(0).offset();
288                     this.itemHeight = itemOffset.height
289                     this.dragTop = offset.top;
290                     this.dragHeight = this.dragEl[0].scrollHeight;
291                     var s = '';
292                 },
293                 bindEvent: function () {
294                     var scope = this;
295                     document.addEventListener("touchstart", function (e) {
296                         scope.touchStart.call(scope, e);
297                     }, false);
298                     document.addEventListener("touchend", function (e) {
299                         scope.touchEnd.call(scope, e);
300                     }, false);
301                     document.addEventListener("touchmove", function (e) {
302                         scope.touchMove.call(scope, e);
303                     }, false);
304                 },
305                 touchStart: function (e) {
306                     if (this.cooling) return false; //冷却时间不能开始
307 
308                     //需要判断是否是拉取元素,此处需要递归验证,这里暂时不管
309                     //!!!!!!!!此处不严谨
310                     var el = $(e.srcElement).parent(), pos;
311                     if (el.hasClass('ul-list')) {
312                         this.moveAble = true;
313 
314                         this.touchTime = e.timeStamp;
315                         //获取鼠标信息
316                         pos = this.getMousePos(e.changedTouches[0]);
317                         //注意,此处是相对位置,注意该处还与动画有关,所以高度必须动态计算
318                         //可以设置一个冷却时间参数,但想想还是算了
319                         //最后还是使用了冷却时间
320                         //                        var top = parseFloat(this.dragEl.css('top')) || 0;
321                         //                        this.mouseY = pos.top - top;
322                         this.mouseY = pos.top - this.curTop;
323                         this.moveAble = true;
324                     }
325                 },
326                 touchMove: function (e) {
327                     if (!this.moveAble) return false;
328                     var pos = this.getMousePos(e.changedTouches[0]);
329                     //先获取相对容器的位置,在将两个鼠标位置相减
330                     this.curTop = pos.top - this.mouseY;
331                     this.dragEl.css('top', this.curTop + 'px');
332                     e.preventDefault();
333                 },
334                 touchEnd: function (e) {
335                     if (!this.moveAble) return false;
336                     this.cooling = true; //开启冷却时间
337 
338                     //时间间隔
339                     var scope = this;
340                     this.timeGap = e.timeStamp - this.touchTime;
341                     var flag = this.oTop <= this.curTop ? 1 : -1; //判断是向上还是向下滚动
342                     var flag2 = this.curTop > 0 ? 1 : -1; //这个会影响后面的计算结果
343                     this.moveState = flag > 0 ? 'up' : 'down';
344                     var ih = parseFloat(this.itemHeight);
345                     var ih1 = ih / 2;
346 
347                     var top = Math.abs(this.curTop);
348                     var mod = top % ih;
349                     top = (parseInt(top / ih) * ih + (mod > ih1 ? ih : 0)) * flag2;
350 
351                     var step = parseInt(this.timeGap / 50);
352                     step = step > 0 ? step : 0;
353                     var speed = this.animateParam[step] || 0;
354                     var increment = speed * ih * flag
355                     top += increment;
356                     //!!!此处动画可能导致数据不同步,后期改造需要加入冷却时间
357                     if (this.oTop != this.curTop) {
358                         this.dragEl.animate({
359                             top: top + 'px'
360                         }, 100 + (speed * 20), 'ease-out', function () {
361                             var _top = top, t = false; ;
362                             if (top > ih) {
363                                 _top = ih;
364                                 t = true;
365                             }
366                             if (top < 0 && (top + scope.dragHeight < ih * 2)) {
367                                 t = true;
368                                 _top = (scope.dragHeight - ih * 2) * (-1);
369                             }
370                             if (t) {
371                                 scope.dragEl.animate({
372                                     top: _top + 'px'
373                                 }, 10, 'ease-in-out', function () {
374                                     scope.oTop = _top;
375                                     scope.curTop = _top;
376                                     scope.cooling = false; //关闭冷却时间
377                                     scope.onTouchEnd();
378                                 });
379                             } else {
380                                 scope.cooling = false; //关闭冷却时间
381                                 scope.oTop = top;
382                                 scope.curTop = top;
383                                 scope.onTouchEnd();
384                             }
385                         });
386                     } else {
387                         this.cooling = false; //关闭冷却时间
388                         this.onTouchEnd();
389                     }
390                     this.moveAble = false;
391                 },
392                 onTouchEnd: function () {
393                     var i = parseInt((this.curTop - this.itemHeight) / parseFloat(this.itemHeight));
394                     this.selectedIndex = Math.abs(i);
395                     var secItem = this.data[this.selectedIndex];
396                     //触发变化事件
397                     var changed = this._changed;
398                     if (changed && typeof changed == 'function') {
399                         changed.call(this, secItem);
400                     }
401                     console.log(this.selectedIndex, secItem);
402                 },
403                 setKey: function (k) { },
404                 setVal: function (v) { },
405                 setIndex: function (i) {
406                     var i = parseInt(i);
407                     if (i >= this.data.length || i < 0) return false;
408 
409                     this.selectedIndex = i;
410                     this.curTop = (i * this.itemHeight * (-1) + this.itemHeight);
411                     this.dragEl.css('top', this.curTop + 'px');
412                 },
413                 getSelected: function () {
414                     return this.data[this.selectedIndex];
415                 },
416                 getByKey: function (k) { },
417                 getByVal: function (v) { },
418                 getByIndex: function (i) { },
419                 //获取鼠标信息
420                 getMousePos: function (event) {
421                     var top, left;
422                     top = Math.max(document.body.scrollTop, document.documentElement.scrollTop);
423                     left = Math.max(document.body.scrollLeft, document.documentElement.scrollLeft);
424                     return {
425                         top: top + event.clientY,
426                         left: left + event.clientX
427                     };
428                 }
429             };
430             window.ScrollRadio = ScrollRadio;
431 
432         })();
433 
434         var data = [];
435         for (var i = 0; i < 20; i++) {
436             var temp = { val: '选项-' + i };
437             data.push(temp);
438         }
439 
440 
441 
442         var myScroll = new ScrollRadio({
443             wrapper: $('#ctripPage'),
444             data: data
445         });
446 
447         $('#set').click(function () {
448             var i = prompt("请输入索引值")
449             if (i != null && i != "") {
450                 myScroll.setIndex(i);
451             }
452         });
453 
454         $('#get').click(function () {
455             var d = myScroll.getSelected();
456             var str = '';
457             for (var k in d) {
458                 str += k + ': ' + d[k] + ',';
459             }
460             alert(str);
461         });
462 
463         var s = '';
464 
465     </script>
466 </body>
467 </html>
View Code

我们这里简单看看代码:

  1 (function () {
  2     //!!!由于动画原因,获取值可能会出现不准确的情况,比如正在动画却已经取值了
  3     //所以设置了一个冷却时间,在冷却时间的情况下设置值等操作不能进行
  4     //为了保证唯一性,全部使用index作为索引算了
  5     var ScrollRadio = function (opts) {
  6         opts = opts || {};
  7         //容器元素
  8         this.wrapper = opts.wrapper || $(document);
  9         this.body = [
 10     '<div class="cui-roller">',
 11         '<ul class="ul-list" style=" position: absolute;  100%; z-index: 2;  " >',
 12         '</ul>',
 13         '<div class="cui-mask"></div>',
 14         '<div class="cui-lines">&nbsp;</div>',
 15     '</div>'
 16 ].join('');
 17         this.body = $(this.body);
 18 
 19         //真正拖动的元素(现在是ul)
 20         this.dragEl = this.body.find('.ul-list');
 21         //数据源
 22         this.data = opts.data || [];
 23         this._changed = opts.changed || null;
 24         //当前选项索引默认选择2项
 25         this.selectedIndex = 1;
 26 
 27         //当前选项值
 28         //                this.key = '';
 29         //当前选项显示的值
 30         //                this.value = '';
 31 
 32         /*
 33         定位实际需要用到的信息
 34         暂时不考虑水平移动吧
 35         */
 36         this.itemHeight = 0; //单个item高度
 37         this.dragHeight = 0; //拖动元素高度
 38         this.dragTop = 0; //拖动元素top
 39         this.animateParam = [10, 6, 2, 1, 0, 0, 0, 0, 0, 0, 0]; //动画参数
 40         this.timeGap = 0; //时间间隔
 41         this.touchTime = 0; //开始时间
 42         this.moveAble = false; //是否正在移动
 43         this.moveState = 'up'; //移动状态,up right down left
 44         this.oTop = 0; //拖动前的top值
 45         this.curTop = 0; //当前容器top
 46         this.mouseY = 0; //鼠标第一次点下时相对父容器的位置
 47         this.cooling = false; //是否处于冷却时间
 48 
 49         this.init();
 50     };
 51     ScrollRadio.prototype = {
 52         constructor: ScrollRadio,
 53         init: function () {
 54             this.initItem();
 55             this.wrapper.append(this.body);
 56             this.initEventParam();
 57             this.bindEvent();
 58 
 59             return this;
 60         },
 61         //增加数据
 62         initItem: function () {
 63             var _tmp, _data, i, k;
 64             for (var i in this.data) {
 65                 _data = this.data[i]
 66                 _tmp = $('<li>' + (_data.val == undefined ? i : _data.val) + '</li>');
 67                 _tmp.attr('data-index', i);
 68                 for (k in _data) {
 69                     _tmp.attr('data-' + k, _data[k]);
 70                 }
 71                 this.dragEl.append(_tmp);
 72             }
 73         },
 74         //初始化事件需要用到的参数信息
 75         initEventParam: function () {
 76             var offset = this.dragEl.offset();
 77             var itemOffset = this.dragEl.find('li').eq(0).offset();
 78             this.itemHeight = itemOffset.height
 79             this.dragTop = offset.top;
 80             this.dragHeight = this.dragEl[0].scrollHeight;
 81             var s = '';
 82         },
 83         bindEvent: function () {
 84             var scope = this;
 85             document.addEventListener("touchstart", function (e) {
 86                 scope.touchStart.call(scope, e);
 87             }, false);
 88             document.addEventListener("touchend", function (e) {
 89                 scope.touchEnd.call(scope, e);
 90             }, false);
 91             document.addEventListener("touchmove", function (e) {
 92                 scope.touchMove.call(scope, e);
 93             }, false);
 94         },
 95         touchStart: function (e) {
 96             if (this.cooling) return false; //冷却时间不能开始
 97 
 98             //需要判断是否是拉取元素,此处需要递归验证,这里暂时不管
 99             //!!!!!!!!此处不严谨
100             var el = $(e.srcElement).parent(), pos;
101             if (el.hasClass('ul-list')) {
102                 this.moveAble = true;
103 
104                 this.touchTime = e.timeStamp;
105                 //获取鼠标信息
106                 pos = this.getMousePos(e.changedTouches[0]);
107                 //注意,此处是相对位置,注意该处还与动画有关,所以高度必须动态计算
108                 //可以设置一个冷却时间参数,但想想还是算了
109                 //最后还是使用了冷却时间
110                 //                        var top = parseFloat(this.dragEl.css('top')) || 0;
111                 //                        this.mouseY = pos.top - top;
112                 this.mouseY = pos.top - this.curTop;
113                 this.moveAble = true;
114             }
115         },
116         touchMove: function (e) {
117             if (!this.moveAble) return false;
118             var pos = this.getMousePos(e.changedTouches[0]);
119             //先获取相对容器的位置,在将两个鼠标位置相减
120             this.curTop = pos.top - this.mouseY;
121             this.dragEl.css('top', this.curTop + 'px');
122             e.preventDefault();
123         },
124         touchEnd: function (e) {
125             if (!this.moveAble) return false;
126             this.cooling = true; //开启冷却时间
127 
128             //时间间隔
129             var scope = this;
130             this.timeGap = e.timeStamp - this.touchTime;
131             var flag = this.oTop <= this.curTop ? 1 : -1; //判断是向上还是向下滚动
132             var flag2 = this.curTop > 0 ? 1 : -1; //这个会影响后面的计算结果
133             this.moveState = flag > 0 ? 'up' : 'down';
134             var ih = parseFloat(this.itemHeight);
135             var ih1 = ih / 2;
136 
137             var top = Math.abs(this.curTop);
138             var mod = top % ih;
139             top = (parseInt(top / ih) * ih + (mod > ih1 ? ih : 0)) * flag2;
140 
141             var step = parseInt(this.timeGap / 50);
142             step = step > 0 ? step : 0;
143             var speed = this.animateParam[step] || 0;
144             var increment = speed * ih * flag
145             top += increment;
146             //!!!此处动画可能导致数据不同步,后期改造需要加入冷却时间
147             if (this.oTop != this.curTop) {
148                 this.dragEl.animate({
149                     top: top + 'px'
150                 }, 100 + (speed * 20), 'ease-out', function () {
151                     var _top = top, t = false; ;
152                     if (top > ih) {
153                         _top = ih;
154                         t = true;
155                     }
156                     if (top < 0 && (top + scope.dragHeight < ih * 2)) {
157                         t = true;
158                         _top = (scope.dragHeight - ih * 2) * (-1);
159                     }
160                     if (t) {
161                         scope.dragEl.animate({
162                             top: _top + 'px'
163                         }, 10, 'ease-in-out', function () {
164                             scope.oTop = _top;
165                             scope.curTop = _top;
166                             scope.cooling = false; //关闭冷却时间
167                             scope.onTouchEnd();
168                         });
169                     } else {
170                         scope.cooling = false; //关闭冷却时间
171                         scope.oTop = top;
172                         scope.curTop = top;
173                         scope.onTouchEnd();
174                     }
175                 });
176             } else {
177                 this.cooling = false; //关闭冷却时间
178                 this.onTouchEnd();
179             }
180             this.moveAble = false;
181         },
182         onTouchEnd: function () {
183             var i = parseInt((this.curTop - this.itemHeight) / parseFloat(this.itemHeight));
184             this.selectedIndex = Math.abs(i);
185             var secItem = this.data[this.selectedIndex];
186             //触发变化事件
187             var changed = this._changed;
188             if (changed && typeof changed == 'function') {
189                 changed.call(this, secItem);
190             }
191             console.log(this.selectedIndex, secItem);
192         },
193         setKey: function (k) { },
194         setVal: function (v) { },
195         setIndex: function (i) {
196             var i = parseInt(i);
197             if (i >= this.data.length || i < 0) return false;
198 
199             this.selectedIndex = i;
200             this.curTop = (i * this.itemHeight * (-1) + this.itemHeight);
201             this.dragEl.css('top', this.curTop + 'px');
202         },
203         getSelected: function () {
204             return this.data[this.selectedIndex];
205         },
206         getByKey: function (k) { },
207         getByVal: function (v) { },
208         getByIndex: function (i) { },
209         //获取鼠标信息
210         getMousePos: function (event) {
211             var top, left;
212             top = Math.max(document.body.scrollTop, document.documentElement.scrollTop);
213             left = Math.max(document.body.scrollLeft, document.documentElement.scrollLeft);
214             return {
215                 top: top + event.clientY,
216                 left: left + event.clientX
217             };
218         }
219     };
220     window.ScrollRadio = ScrollRadio;
221 
222 })();

以上代码基本框架都出来了,也有注释,有兴趣的朋友自己看看,我们现在进行最后一步了,将日历搞上去,老夫来不起了。。。

日历插件:)

http://sandbox.runjs.cn/show/prii13pm

  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 /*reset*/
  8 body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td,hr,button,article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{margin:0;padding:0}
  9 body,button,input,select,textarea{font:normal 14px/1.5 Tahoma,"Lucida Grande",Verdana,"Microsoft YaHei",hei;}
 10 article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section,iframe{display:block;}
 11 h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:500;}
 12 address,cite,dfn,em,var,i{font-style:normal;font-weight:normal;font-family:arial;}
 13 ul,ol{list-style:none}
 14 a{color:#000;text-decoration:none}
 15 a:hover{text-decoration:underline;-webkit-transition:color .2s linear;-moz-transition:color .2s linear;-ms-transition:color .2s linear;-o-transition:color .2s linear;transition:color .2s linear;}
 16 fieldset,img,button,input{border:0}
 17 button,input,select,textarea{font-size:100%}
 18 table{border-collapse:collapse;border-spacing:0}
 19 input[type="button"],input[type="submit"]{-webkit-appearance:none;}
 20 body{min-width:320px; background:#f5f5f5;overflow-x:hidden;-webkit-text-size-adjust:none;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-font-smoothing:subpixel-antialiased;-moz-user-select:none;color:#000;}:focus{outline:none;}.clearfix:after{clear:both;content:'.';display:block;height:0;visibility:hidden;line-height:0;}.clearfix{*zoom:1;}.fl{float:left;}.fr{float:right;}.clear{clear:both;}.overflow{overflow:hidden;}.ellips{white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}.ellips_line2,.ellips_line3{display: -webkit-box;-webkit-box-orient: vertical;overflow: hidden;}.ellips_line2{-webkit-line-clamp:2;}.ellips_line3{-webkit-line-clamp:3;}.pos_rel{position:relative;}
 21 html,body,.h100{ height:100%; }
 22 dfn{color:#ff9913; font-size:12px; font-weight:normal;}
 23 /*-----------------------------------------common--------------------*/
 24 .i,.i_bef:before,.i_aft:after,.carlist li:before,.ok_crt:after{background:url(../img/style1/v2_bgs.png) no-repeat; background-size:175px 125px;}
 25 .i_bef:before,.i_aft:after,.carlist li:before{position: absolute;content: "";}
 26 .abs_size{-moz-box-sizing:border-box; -webkit-box-sizing:border-box; box-sizing:border-box;}
 27 .opacity{opacity:0.7; filter:alpha(opacity=70);}
 28 
 29 /*active*/
 30 .list_st_border li:active,.p_hinttxt:active,.search_cancel:active,.citylist dd:active{ background:#f8f8f8;}
 31 .btn_yellow:active{background:#eb840f;}
 32 
 33 /*layout*/
 34 .wrap{margin-top:48px;}
 35 .wrap_pb{margin-top:48px; padding-bottom:45px;}
 36 .p10{padding:10px;}
 37 .hm{text-align:center;}
 38 .break_all{word-break:break-all;}
 39 .fix_b{position:fixed; bottom:0; left:0;z-index:9999;}
 40 
 41 /*font bg color size*/
 42 h1{font:normal 1.286em/1.5 "";}/*18px*/
 43 h2{font:normal 1.143em/1.5 "";}/*16px*/
 44 h3{font:600 1em/1.5 "";}/*14px*/
 45 .price{margin-left:5px;}
 46 .price i{margin-left:2px; font-size:1.286em;}
 47 .greyfont{color:#686868;}
 48 .greyfont1{color:#909090;}
 49 .bggrey{height:100%; background:#f5f5f5;}
 50 
 51 /*header*/
 52 header{position:fixed; top:0; left:0; z-index:9999; width:100%; height:48px;background-color:#1491c5;}
 53 .returnico{position:absolute; left:0; top:0;  width:68px; height:48px; background-color:#15a4d5;}
 54 .returnico:before{left:25px;top:16px;width:12px;height:20px; background-position:0 0;}
 55 .icon_phone,.icon_home{width:42px;height:100%;top:0;position:relative;float:right;}
 56 .icon_phone:before{width:11px;height:20px;top:16px;right:12px;background-position:-115px -65px;}
 57 .icon_home:before{width:20px;height:19px;top:16px;right:10px;background-position:-83px -66px;}
 58 header i:active{opacity:0.7; filter:alpha(opacity=70);}
 59 header h1{position:absolute; width:100%;line-height:48px; text-align:center; letter-spacing:2px; color: #fff;}
 60 .header_r,.header_rs{position:absolute;z-index:9; top:0; right:0; line-height:48px; padding:0 15px; font-size:18px; background:#15a4d5; color:#fff;}
 61 .header_rs{padding:0 5px; font-size:12px; }
 62 
 63 /*background-position*/
 64 .select_n:before{width:20px;height:20px;background-position:-18px 0;}
 65 .select_n.current:before{background-position:-44px 0;}
 66 
 67 /*searchbox*/
 68 .search_wrap{overflow:hidden; padding:10px; background:#dfeaf1;}
 69 .search_box{position:relative; float:left; width:100%;}
 70 .search_input{width:100%; padding:0 10px 0 28px; line-height:30px; background-color:#fff; border-radius:4px; color:#ccc;}
 71 .fdj:before,.fdj:after,.search_box:before,.search_box:after{position:absolute; content:""; z-index:9;}
 72 .fdj:before,.search_box:before{left:5px; top:7px; width:12px; height:12px; border:1px solid #bcbcbc; border-radius:12px;}
 73 .fdj:after,.search_box:after{left:19px; top:17px; width:1px; height:8px; background:#bcbcbc;}
 74 .search_cancel{ display:none;float:left; width:20%; line-height:30px; text-align:center; font-size:16px;color:#1491c5; background:none; border:none;}
 75 .close_icon{display:none; position:absolute; z-index:10; top:8px; right:4px; width:16px; height:16px; border-radius:30px; background:#b1b1b1;}
 76 .close_icon:before,.close_icon:after{position:absolute; content:""; top:4px; left:7px; width:2px; height:8px; background:#fff; }
 77 .close_icon:before{-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg);}
 78 .fdj:after,.search_box:after,.close_icon:after{-webkit-transform:rotate(-45deg);-moz-transform:rotate(-45deg);-ms-transform:rotate(-45deg);-o-transform:rotate(-45deg);transform:rotate(-45deg);}
 79 .search_focus .search_box{width:80%;}
 80 .search_focus .close_icon, .search_focus .search_cancel{display:block;}
 81 .search_input:focus{color:#000;}
 82 
 83 /*tab*/
 84 .tab{ background-color:#f8f8f8; border-bottom:1px solid #dfdfdf;}
 85 .tab li{float:left; width:50%; height:39px; line-height:39px; text-align:center; border-right:1px solid #dfdfdf;}
 86 .tab li:last-child{border-right:none;}
 87 .tab li.tabcrt{ background-color:#dfdfdf;}
 88 
 89 .tab_b{ background-color:#f5f5f5; border-bottom:1px solid #c1c1c1;}
 90 .tab_b li{float:left; width:50%; height:39px; line-height:39px; text-align:center;}
 91 .tab_b li:last-child{border-right:none;}
 92 .tab_b li.tabcrt{color:#1491c5; border-bottom:4px solid #1491c5;}
 93 
 94 /*list*/
 95 .list_st_border{ background:#fff; border-bottom:none; border:1px solid #cfcfcf; }
 96 .list_st_border li{position:relative;padding:0 10px; line-height:42px; border-bottom:1px solid #cfcfcf;}
 97 .list_st_border li:last-child{border-bottom:none;}
 98 
 99 .list_sli{padding:10px; overflow:hidden; border-bottom:1px solid #cfcfcf; background:#fff;}
100 .list_sli .list_sunit{float:left;}
101 
102 .citylist{color:#000;}
103 .citylist dt,.citylist dd{padding-left:10px;border-bottom:1px solid #e2e2e2;}
104 .citylist dt{line-height:25px; background-color:#eaeaea;}
105 .citylist dd{position:relative; font-size:16px; line-height:43px; background-color:#fff;}
106 .citylist .ok_crt{color:#1491c5;}
107 .citylist .ok_crt:after{position:absolute;content:""; right:10px; top:50%; margin-top:-6px; width:12px; height:13px; background-position:-110px 0;}
108 
109 
110 /*arr*/
111 .li_arr_r{position:relative;}
112 .arr_r{position:absolute;right:0px; top:50%; width:30px; height:30px; margin-top:-15px; }
113 .arr_r:before,.arr_r:after,.li_arr_r:before,.li_arr_r:after{position: absolute; left:15px; content: "";width:2px; height:7px;  background-color:#909090;}
114 .arr_r:before,.li_arr_r:before{top:10px;-webkit-transform:rotate(-45deg); -moz-transform:rotate(-45deg);-ms-transform:rotate(-45deg);-o-transform:rotate(-45deg);transform:rotate(-45deg);}
115 .arr_r:after,.li_arr_r:after{top:15px;-webkit-transform:rotate(45deg); -moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg);}
116 .li_arr_r:before,.li_arr_r:after{left:auto; right:10px; top:50%; margin-top:-5px;}
117 .li_arr_r:after{margin-top:0;}
118 
119 /*p*/
120 .p_grey{margin:10px 5px; font-size:13px; color:#989898;}
121 .p_grey_center{ text-align:center; margin:20px 5px; font-size:13px; color:#989898;}
122 .p_hinttxt{padding:20px 10px; text-align:center; font-size:16px;  color:#1491c5;}
123 
124 
125 /*btn*/
126 .btn_yellow,.btn_del{width:100%; height:44px; line-height:42px; padding:0 10px;  color:#fff;}
127 .btn_yellow{background:#ff9913;}
128 .btn_del{background:#ca4345;text-align:center;font-size:1.2em;}
129 
130 .btn_pay{padding:0 20px;height:44px;float:right;background:#ff7d13;color:#fff;}
131 .btn_pay:active{background:#ff7300;}
132 .room_num {position:absolute; right:10px; width:100px; height:30px; line-height:30px;color:#000;background-color: #fff; text-align:center;border:#bfbfbf 1px solid;}
133 .room_num i{position:absolute; width:30px; height:30px; text-align:center; font:normal 2em/28px "Arial";}
134 .room_num i:first-child{left:0;background:#f4f4f4;color:#d9d9d9;font:normal 2.8em/25px "Arial";}
135 .room_num i:last-child{right:0;background:#06a2d0;color:#fff;}
136 
137 
138     /*日历*/
139 .cui_cldwrap{color:#000;}
140 .cui_cldweek{height:25px; overflow:hidden;font:normal 12px/24px "verdana";border-bottom:1px solid #c8c8c8;}
141 .cui_cldweek li{float:left; width:14%; text-align:center; }
142 .cui_cldweek li:first-child,.cui_cldweek li:last-child{width:15%; color:#acacac;}
143 .cui_cldmonth{height:35px;text-align:center;font:normal 16px/35px "verdana"; background:#fff;}
144 .cui_cldunit{margin-bottom:20px;}
145 .cui_cld_daybox{overflow:hidden; background:#fff;}
146 .cui_cld_daybox li{float:left; width:14%; height:45px; padding:4px 0; font:normal 12px/45px "verdana"; overflow:hidden; text-align:center;}
147 .cui_cld_daybox li:nth-child(7n),.cui_cld_daybox li:nth-child(7n+1){width:15%;}
148 .cui_cld_daypass{ background:#f7f7f7;}
149 .cui_cld_daycrt{background:#06a2d0; color:#fff;}
150 .cui_cld_dayfuture{background:#fff;}
151 .cui_cld_day_nocrtmonth{ visibility:hidden;}
152 .cui_cld_day_havetxt em{display:block; line-height:25px;}
153 .cui_cld_day_havetxt i{display:block;line-height:15px;}
154 .cui_cld_day_hint{color:#06a2d0;}
155 /*全局XXXX*/
156 
157 /*弹出蓝色框*/
158 .cui-pop-box{background:#fff;}
159 .cui-text-center{text-align:center;}
160 .cui-pop-box .cui-hd{height:40px;line-height:40px;font-size:1.2em;color:#fff;background:#1491c5;padding:0 10px;position:relative;}
161 .cui-pop-box .cui-hd .cui-close{position:absolute;top:10px; right:10px; width:18px; height:18px;line-height:18px;border-radius:50%; background:#fff;color:#1491c5;text-align:center;font-weight:bold;}
162 .cui-error{width:150px;margin:auto;border-radius:5px;background:rgba(73,73,73,1);padding:10px;color:#fff;font-weight:700;text-align:center;word-break:break-all;}
163 .cui-select-view li{border-bottom:#dfdfdf 1px solid;padding:.8em 2em .8em .8em;white-space:nowrap; overflow:hidden; text-overflow:ellipsis;position:relative;}
164 .cui-select-view li.current{color:#1084bc;}
165 .cui-select-view li:active{background:rgba(0,0,0,.05);}
166 .cui-select-view li.current:before,.cui-select-view li.current:after{position:absolute;content:"";background:#1084bc;height:3px;top:50%;border-radius:3px;}
167 .cui-select-view li.current:before{width:18px;right:10px;margin-top:-2px;-webkit-transform:rotate(-50deg);-moz-transform:rotate(-50deg);-ms-transform:rotate(-50deg);transform:rotate(-50deg);}
168 .cui-select-view li.current:after{width:9px;right:22px;margin-top:2px;-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg);}
169 
170 .cui-roller{width:100%;height:90px;overflow:hidden;position:relative;display: -webkit-box;display: -moz-box;display: -ms-flexbox;display: -webkit-flex;display: flex;}
171 .cui-roller .ul-list{height:100%;text-align:center;font-size:1.1em;line-height:30px;-webkit-box-flex: 1;-moz-box-flex: 1;-webkit-flex: 1;-ms-flex: 1;flex: 1;}
172 .cui-mask{position:absolute;z-index:3;top: 0;left: 0;width: 100%;height: 100%;pointer-events: none;
173     background: linear-gradient(#fff 0,rgba(245,245,245,0) 52%,rgba(245,245,245,0) 48%,#fff 100%);
174     background: -webkit-gradient(linear,left bottom,left top,from(#fff),color-stop(0.52,rgba(245,245,245,0)),color-stop(0.48,rgba(245,245,245,0)),to(#fff));
175     background: -webkit-linear-gradient(#fff 0,rgba(245,245,245,0) 52%,rgba(245,245,245,0) 48%,#fff 100%);
176     background: -moz-linear-gradient(#fff 0,rgba(245,245,245,0) 52%,rgba(245,245,245,0) 48%,#fff 100%);
177 }
178 .cui-lines{width:100%;height:34px;position:absolute;top:50%;margin-top:-17px;border-top:#dfdfdf 1px solid;border-bottom:#dfdfdf 1px solid;}
179 .cui-roller-tips{color:#8d8d8d;padding:5px;text-align:center;}
180 .cui-roller-btns{background:#f6f5f5;padding:10px;text-align:center;}
181 .cui-roller-btns span{width:45%;display:inline-block;padding:10px 0;color:#fff;}
182 .cui-roller-btns span:active{opacity:.75;}
183 .cui-roller-btns .cui-btns-cancel{background:#a9a9a9;margin-right:5%;}
184 .cui-roller-btns .cui-btns-sure{background:#ff9913;}
185 
186     </style>
187     <style type="text/css">
188         .c { position: absolute; top: 0; }
189         #y { left: 0; width: 30%; }
190         #m { left: 30%; right: 40%; }
191         #d { right: 0; width: 40%; }
192     </style>
193     <script src="../zepto.js" type="text/javascript"></script>
194 </head>
195 <body onselectstart="return false">
196     <div class="cui-pop-box">
197         <div class="cui-hd">
198             <div class="cui-text-center">
199                 我是日历控件</div>
200         </div>
201         <div class="cui-bd">
202             <div style="height: 90px; position: relative;">
203                 <div id="y" class="c">
204                 </div>
205                 <div id="m" class="c">
206                 </div>
207                 <div id="d" class="c">
208                 </div>
209             </div>
210             <p class="cui-roller-tips">
211                 点击获取日期吧!</p>
212             <div class="cui-roller-btns">
213                 <span class="cui-btns-cancel" id="set">取消</span> <span class="cui-btns-sure" id="get">
214                     获取日期</span>
215             </div>
216         </div>
217     </div>
218  
219     <script type="text/javascript">
220 
221         //    var myScroll = new iScroll('wl1');
222 
223         (function () {
224             //!!!由于动画原因,获取值可能会出现不准确的情况,比如正在动画却已经取值了
225             //所以设置了一个冷却时间,在冷却时间的情况下设置值等操作不能进行
226             //为了保证唯一性,全部使用index作为索引算了
227             var ScrollRadio = function (opts) {
228                 opts = opts || {};
229                 //容器元素
230                 this.wrapper = opts.wrapper || $(document);
231                 var id = new Date().getTime() + Math.random() + 'id';
232                 this.body = [
233     '<div class="cui-roller">',
234         '<ul class="ul-list" style=" position: absolute;  100%; z-index: 2;  "  id="' + id + '" >',
235         '</ul>',
236         '<div class="cui-mask"></div>',
237         '<div class="cui-lines">&nbsp;</div>',
238     '</div>'
239 ].join('');
240                 this.body = $(this.body);
241 
242                 //真正拖动的元素(现在是ul)
243                 this.dragEl = this.body.find('.ul-list');
244                 //数据源
245                 this.data = opts.data || [];
246                 this._changed = opts.changed || null;
247                 //当前选项索引默认选择2项
248                 this.selectedIndex = 1;
249 
250                 //当前选项值
251                 //                this.key = '';
252                 //当前选项显示的值
253                 //                this.value = '';
254 
255                 /*
256                 定位实际需要用到的信息
257                 暂时不考虑水平移动吧
258                 */
259                 this.itemHeight = 0; //单个item高度
260                 this.dragHeight = 0; //拖动元素高度
261                 this.dragTop = 0; //拖动元素top
262                 this.animateParam = [10, 6, 2, 1, 0, 0, 0, 0, 0, 0, 0]; //动画参数
263                 this.timeGap = 0; //时间间隔
264                 this.touchTime = 0; //开始时间
265                 this.moveAble = false; //是否正在移动
266                 this.moveState = 'up'; //移动状态,up right down left
267                 this.oTop = 0; //拖动前的top值
268                 this.curTop = 0; //当前容器top
269                 this.mouseY = 0; //鼠标第一次点下时相对父容器的位置
270                 this.cooling = false; //是否处于冷却时间
271 
272                 this.init();
273             };
274             ScrollRadio.prototype = {
275                 constructor: ScrollRadio,
276                 init: function () {
277                     this.initItem();
278                     this.wrapper.append(this.body);
279                     this.initEventParam();
280                     this.bindEvent();
281                 },
282                 //增加数据
283                 initItem: function () {
284                     var _tmp, _data, i, k;
285                     for (var i in this.data) {
286                         _data = this.data[i]
287                         _tmp = $('<li>' + (_data.val == undefined ? i : _data.val) + '</li>');
288                         _tmp.attr('data-index', i);
289                         for (k in _data) {
290                             _tmp.attr('data-' + k, _data[k]);
291                         }
292                         this.dragEl.append(_tmp);
293                     }
294                 },
295                 //初始化事件需要用到的参数信息
296                 initEventParam: function () {
297                     var offset = this.dragEl.offset();
298                     var itemOffset = this.dragEl.find('li').eq(0).offset();
299                     this.itemHeight = itemOffset.height
300                     this.dragTop = offset.top;
301                     this.dragHeight = this.dragEl[0].scrollHeight;
302                     var s = '';
303                 },
304                 bindEvent: function () {
305                     var scope = this;
306                     this.dragEl[0].addEventListener("touchstart", function (e) {
307                         scope.touchStart.call(scope, e);
308                     }, false);
309                     this.dragEl[0].addEventListener("touchend", function (e) {
310                         scope.touchEnd.call(scope, e);
311                     }, false);
312                     this.dragEl[0].addEventListener("touchmove", function (e) {
313                         scope.touchMove.call(scope, e);
314                     }, false);
315                 },
316                 touchStart: function (e) {
317                     if (this.cooling) return false; //冷却时间不能开始
318 
319                     //需要判断是否是拉取元素,此处需要递归验证,这里暂时不管
320                     //!!!!!!!!此处不严谨
321                     var el = $(e.srcElement).parent(), pos;
322                     if (el.hasClass('ul-list')) {
323                         this.moveAble = true;
324 
325                         this.touchTime = e.timeStamp;
326                         //获取鼠标信息
327                         pos = this.getMousePos(e.changedTouches[0]);
328                         //注意,此处是相对位置,注意该处还与动画有关,所以高度必须动态计算
329                         //可以设置一个冷却时间参数,但想想还是算了
330                         //最后还是使用了冷却时间
331                         //                        var top = parseFloat(this.dragEl.css('top')) || 0;
332                         //                        this.mouseY = pos.top - top;
333                         this.mouseY = pos.top - this.curTop;
334                         this.moveAble = true;
335                     }
336                 },
337                 touchMove: function (e) {
338                     if (!this.moveAble) return false;
339                     var pos = this.getMousePos(e.changedTouches[0]);
340                     //先获取相对容器的位置,在将两个鼠标位置相减
341                     this.curTop = pos.top - this.mouseY;
342                     this.dragEl.css('top', this.curTop + 'px');
343                     e.preventDefault();
344                 },
345                 touchEnd: function (e) {
346                     if (!this.moveAble) return false;
347                     this.cooling = true; //开启冷却时间
348 
349                     //时间间隔
350                     var scope = this;
351                     this.timeGap = e.timeStamp - this.touchTime;
352                     var flag = this.oTop <= this.curTop ? 1 : -1; //判断是向上还是向下滚动
353                     var flag2 = this.curTop > 0 ? 1 : -1; //这个会影响后面的计算结果
354                     this.moveState = flag > 0 ? 'up' : 'down';
355                     var ih = parseFloat(this.itemHeight);
356                     var ih1 = ih / 2;
357 
358                     var top = Math.abs(this.curTop);
359                     var mod = top % ih;
360                     top = (parseInt(top / ih) * ih + (mod > ih1 ? ih : 0)) * flag2;
361 
362                     var step = parseInt(this.timeGap / 50);
363                     step = step > 0 ? step : 0;
364                     var speed = this.animateParam[step] || 0;
365                     var increment = speed * ih * flag
366                     top += increment;
367                     //!!!此处动画可能导致数据不同步,后期改造需要加入冷却时间
368                     if (this.oTop != this.curTop) {
369                         this.dragEl.animate({
370                             top: top + 'px'
371                         }, 100 + (speed * 20), 'ease-out', function () {
372                             var _top = top, t = false; ;
373                             if (top > ih) {
374                                 _top = ih;
375                                 t = true;
376                             }
377                             if (top < 0 && (top + scope.dragHeight < ih * 2)) {
378                                 t = true;
379                                 _top = (scope.dragHeight - ih * 2) * (-1);
380                             }
381                             if (t) {
382                                 scope.dragEl.animate({
383                                     top: _top + 'px'
384                                 }, 10, 'ease-in-out', function () {
385                                     scope.oTop = _top;
386                                     scope.curTop = _top;
387                                     scope.cooling = false; //关闭冷却时间
388                                     scope.onTouchEnd();
389                                 });
390                             } else {
391                                 scope.cooling = false; //关闭冷却时间
392                                 scope.oTop = top;
393                                 scope.curTop = top;
394                                 scope.onTouchEnd();
395                             }
396                         });
397                     } else {
398                         this.cooling = false; //关闭冷却时间
399                         this.onTouchEnd();
400                     }
401                     this.moveAble = false;
402                 },
403                 onTouchEnd: function () {
404                     var i = parseInt((this.curTop - this.itemHeight) / parseFloat(this.itemHeight));
405                     this.selectedIndex = Math.abs(i);
406                     var secItem = this.data[this.selectedIndex];
407                     //触发变化事件
408                     var changed = this._changed;
409                     if (changed && typeof changed == 'function') {
410                         changed.call(this, secItem);
411                     }
412                     console.log(this.selectedIndex, secItem);
413                 },
414                 setKey: function (k) { },
415                 setVal: function (v) { },
416                 setIndex: function (i) {
417                     var i = parseInt(i);
418                     if (i >= this.data.length || i < 0) return false;
419 
420                     this.selectedIndex = i;
421                     this.curTop = (i * this.itemHeight * (-1) + this.itemHeight);
422                     this.dragEl.css('top', this.curTop + 'px');
423                 },
424                 getSelected: function () {
425                     return this.data[this.selectedIndex];
426                 },
427                 getByKey: function (k) { },
428                 getByVal: function (v) { },
429                 getByIndex: function (i) { },
430                 //获取鼠标信息
431                 getMousePos: function (event) {
432                     var top, left;
433                     top = Math.max(document.body.scrollTop, document.documentElement.scrollTop);
434                     left = Math.max(document.body.scrollLeft, document.documentElement.scrollLeft);
435                     return {
436                         top: top + event.clientY,
437                         left: left + event.clientX
438                     };
439                 }
440             };
441             window.ScrollRadio = ScrollRadio;
442 
443         })();
444 
445         var yy = [];
446         for (var i = 0; i < 150; i++) {
447             var temp = { val: 1900 + i };
448             yy.push(temp);
449         }
450 
451         var mm = [];
452         for (var i = 0; i < 12; i++) {
453             var temp = { val: i > 10 ? i : (0 + '' + i) };
454             mm.push(temp);
455         }
456 
457         var dd = [];
458         for (var i = 0; i < 31; i++) {
459             var temp = { val: i > 10 ? i : (0 + '' + i) };
460             dd.push(temp);
461         }
462 
463         var y = new ScrollRadio({
464             wrapper: $('#y'),
465             data: yy
466         });
467         var m = new ScrollRadio({
468             wrapper: $('#m'),
469             data: mm
470         });
471         var d = new ScrollRadio({
472             wrapper: $('#d'),
473             data: dd
474         });
475 
476         $('#get').click(function () {
477             alert(y.getSelected().val + '-' + m.getSelected().val + '-' + d.getSelected().val);
478         });
479 
480         var s = '';
481 
482     </script>
483 </body>
484 </html>
View Code

今天时间用多了,老夫有点来不起了,我们下次再完善吧。。。。。。

结语

若是各位觉得有用的话不妨用一用,发现什么BUG请留言,我下次一并更新,BUG应该很多的。 

原文地址:https://www.cnblogs.com/yexiaochai/p/3322477.html