Browse Source

时间控件

jack 7 years ago
parent
commit
3562a5e149

+ 10 - 2
app/html/updateEdu-edit.html

@ -45,7 +45,7 @@
45 45
    			</div>
46 46
		    </div>
47 47
		    <div class="mui-input-group mainbox">
48
				<div class="infocontit infocontitM OnetitM mui-navigate-right mui-clearfix" id='showYearPicker' data-options='{"type":"year","beginYear":1900,"endYear":2020}'>
48
				<div class="infocontit infocontitM OnetitM mui-navigate-right mui-clearfix" id='showYearPicker' data-options='{"type":"year","beginYear":1900,"endYear":2020,"hasToCurr":true}'>
49 49
    				<span class="mui-pull-left">毕业时间</span>
50 50
				    <span class="rightword" id="yearResult">请选择毕业时间</span>
51 51
    			</div>
@ -61,6 +61,8 @@
61 61
		<script src="../js/public/mui.min.js"></script>
62 62
		<script src="../js/public/zepto.min.js"></script>
63 63
		<script src="../js/public/mui.picker.min.js"></script>
64
		<script src="../js/public/mui.picker.js"></script>
65
		<script src="../js/public/mui.dtpicker.js"></script>
64 66
		<script src="../js/public/city.data.js"></script>
65 67
		<script src="../js/public/base.js"></script>
66 68
		<script type="text/javascript" src="../js/updateEdu-edit.js"></script>
@ -119,6 +121,7 @@
119 121
					 * 示例为了简洁,将 options 放在了按钮的 dom 上
120 122
					 * 也可以直接通过代码声明 optinos 用于实例化 DtPicker
121 123
					 */
124
					options.endYear=new Date().getFullYear()
122 125
					var picker = new $.DtPicker(options);
123 126
					picker.show(function(rs) {
124 127
						/*
@ -130,7 +133,12 @@
130 133
						 * rs.h 时,用法同年
131 134
						 * rs.i 分(minutes 的第二个字母),用法同年
132 135
						 */
133
						result.innerText =  rs.y.text +"年";
136
						if(rs.y.text=="至今") {
137
								result.innerText =  "至今"
138
							}else{
139
								result.innerText =  rs.y.text +"年";
140
							}
141
						
134 142
						/* 
135 143
						 * 返回 false 可以阻止选择框的关闭
136 144
						 * return false;

+ 10 - 3
app/html/updateJob-edit.html

@ -45,7 +45,7 @@
45 45
    			</div>
46 46
		    </div>
47 47
		    <div class="mui-input-group mainbox">
48
				<div class="infocontit infocontitM OnetitM mui-navigate-right mui-clearfix showMPicker" data-options='{"type":"month","beginYear":1900,"endYear":2020}'>
48
				<div class="infocontit infocontitM OnetitM mui-navigate-right mui-clearfix showMPicker" data-options='{"type":"month","beginYear":1900,"endYear":2020,"hasToCurr":true}'>
49 49
    				<span class="mui-pull-left">结束时间</span>
50 50
				    <span class="rightword MResult" id="stopMonth">请选择结束时间</span>
51 51
    			</div>
@ -60,7 +60,8 @@
60 60
		</div>
61 61
		<script src="../js/public/mui.min.js"></script>
62 62
		<script src="../js/public/zepto.min.js"></script>
63
		<script src="../js/public/mui.picker.min.js"></script>
63
		<script src="../js/public/mui.picker.js"></script>
64
		<script src="../js/public/mui.dtpicker.js"></script>
64 65
		<script src="../js/public/city.data.js"></script>
65 66
		<script src="../js/public/base.js"></script>
66 67
		<script type="text/javascript" src="../js/updateJob-edit.js"></script>	
@ -76,6 +77,7 @@
76 77
						var optionsJson = this.getAttribute('data-options') || '{}';
77 78
						var options = JSON.parse(optionsJson);
78 79
						var id = this.getAttribute('id');
80
						options.endYear=new Date().getFullYear();
79 81
						/*
80 82
						 * 首次显示时实例化组件
81 83
						 * 示例为了简洁,将 options 放在了按钮的 dom 上
@ -92,7 +94,12 @@
92 94
							 * rs.h 时,用法同年
93 95
							 * rs.i 分(minutes 的第二个字母),用法同年
94 96
							 */
95
							result[i].innerText =  rs.y.text +"年" + rs.m.text +"月";
97
							if(rs=="9999") {
98
								result[i].innerText =  "至今"
99
							}else{
100
								result[i].innerText =  rs.y.text +"年" + rs.m.text +"月";
101
							}
102
							
96 103
							/* 
97 104
							 * 返回 false 可以阻止选择框的关闭
98 105
							 * return false;

+ 10 - 3
app/html/updateProject-edit.html

@ -33,7 +33,7 @@
33 33
    			</div>
34 34
		    </div>
35 35
		    <div class="mui-input-group mainbox">
36
				<div class="infocontit infocontitM OnetitM mui-navigate-right mui-clearfix showMPicker" data-options='{"type":"month","beginYear":1900,"endYear":2020}'>
36
				<div class="infocontit infocontitM OnetitM mui-navigate-right mui-clearfix showMPicker" data-options='{"type":"month","beginYear":1900,"endYear":2020,"hasToCurr":true}'>
37 37
    				<span class="mui-pull-left">结束时间</span>
38 38
				    <span class="rightword MResult" id="stopMonth">请选择结束时间</span>
39 39
    			</div>
@ -54,7 +54,8 @@
54 54
		</div>
55 55
		<script src="../js/public/mui.min.js"></script>
56 56
		<script src="../js/public/zepto.min.js"></script>
57
		<script src="../js/public/mui.picker.min.js"></script>
57
		<script src="../js/public/mui.picker.js"></script>
58
		<script src="../js/public/mui.dtpicker.js"></script>
58 59
		<script src="../js/public/city.data.js"></script>
59 60
		<script src="../js/public/base.js"></script>
60 61
		<script type="text/javascript" src="../js/updateProject-edit.js"></script>	
@ -70,6 +71,7 @@
70 71
						var optionsJson = this.getAttribute('data-options') || '{}';
71 72
						var options = JSON.parse(optionsJson);
72 73
						var id = this.getAttribute('id');
74
						options.endYear=new Date().getFullYear()
73 75
						/*
74 76
						 * 首次显示时实例化组件
75 77
						 * 示例为了简洁,将 options 放在了按钮的 dom 上
@ -86,7 +88,12 @@
86 88
							 * rs.h 时,用法同年
87 89
							 * rs.i 分(minutes 的第二个字母),用法同年
88 90
							 */
89
							result[i].innerText =  rs.y.text +"年" + rs.m.text +"月";
91
							if(rs=="9999") {
92
								result[i].innerText =  "至今"
93
							}else{
94
								result[i].innerText =  rs.y.text +"年" + rs.m.text +"月";
95
							}
96
							
90 97
							/* 
91 98
							 * 返回 false 可以阻止选择框的关闭
92 99
							 * return false;

+ 488 - 0
app/js/public/mui.dtpicker.js

@ -0,0 +1,488 @@
1
/**
2
 * 日期时间插件
3
 * varstion 1.0.5
4
 * by Houfeng
5
 * Houfeng@DCloud.io
6
 */
7
8
(function($, document) {
9
10
	//创建 DOM
11
	$.dom = function(str) {
12
		if (typeof(str) !== 'string') {
13
			if ((str instanceof Array) || (str[0] && str.length)) {
14
				return [].slice.call(str);
15
			} else {
16
				return [str];
17
			}
18
		}
19
		if (!$.__create_dom_div__) {
20
			$.__create_dom_div__ = document.createElement('div');
21
		}
22
		$.__create_dom_div__.innerHTML = str;
23
		return [].slice.call($.__create_dom_div__.childNodes);
24
	};
25
26
	var domBuffer = '<div class="mui-dtpicker" data-type="datetime">\
27
		<div class="mui-dtpicker-header">\
28
			<button data-id="btn-cancel" class="mui-btn">取消</button>\
29
			<button data-id="btn-ok" class="mui-btn mui-btn-blue">确定</button>\
30
		</div>\
31
		<div class="mui-dtpicker-title"><h5 data-id="title-y">年</h5><h5 data-id="title-m">月</h5><h5 data-id="title-d">日</h5><h5 data-id="title-h">时</h5><h5 data-id="title-i">分</h5></div>\
32
		<div class="mui-dtpicker-body">\
33
			<div data-id="picker-y" class="mui-picker">\
34
				<div class="mui-picker-inner">\
35
					<div class="mui-pciker-rule mui-pciker-rule-ft"></div>\
36
					<ul class="mui-pciker-list">\
37
					</ul>\
38
					<div class="mui-pciker-rule mui-pciker-rule-bg"></div>\
39
				</div>\
40
			</div>\
41
			<div data-id="picker-m" class="mui-picker">\
42
				<div class="mui-picker-inner">\
43
					<div class="mui-pciker-rule mui-pciker-rule-ft"></div>\
44
					<ul class="mui-pciker-list">\
45
					</ul>\
46
					<div class="mui-pciker-rule mui-pciker-rule-bg"></div>\
47
				</div>\
48
			</div>\
49
			<div data-id="picker-d" class="mui-picker">\
50
				<div class="mui-picker-inner">\
51
					<div class="mui-pciker-rule mui-pciker-rule-ft"></div>\
52
					<ul class="mui-pciker-list">\
53
					</ul>\
54
					<div class="mui-pciker-rule mui-pciker-rule-bg"></div>\
55
				</div>\
56
			</div>\
57
			<div data-id="picker-h" class="mui-picker">\
58
				<div class="mui-picker-inner">\
59
					<div class="mui-pciker-rule mui-pciker-rule-ft"></div>\
60
					<ul class="mui-pciker-list">\
61
					</ul>\
62
					<div class="mui-pciker-rule mui-pciker-rule-bg"></div>\
63
				</div>\
64
			</div>\
65
			<div data-id="picker-i" class="mui-picker">\
66
				<div class="mui-picker-inner">\
67
					<div class="mui-pciker-rule mui-pciker-rule-ft"></div>\
68
					<ul class="mui-pciker-list">\
69
					</ul>\
70
					<div class="mui-pciker-rule mui-pciker-rule-bg"></div>\
71
				</div>\
72
			</div>\
73
		</div>\
74
	</div>';
75
76
	//plugin
77
	var DtPicker = $.DtPicker = $.Class.extend({
78
		init: function(options) {
79
			var self = this;
80
			var _picker = $.dom(domBuffer)[0];
81
			document.body.appendChild(_picker);
82
			$('[data-id*="picker"]', _picker).picker();
83
			var ui = self.ui = {
84
				picker: _picker,
85
				mask: $.createMask(),
86
				ok: $('[data-id="btn-ok"]', _picker)[0],
87
				cancel: $('[data-id="btn-cancel"]', _picker)[0],
88
				y: $('[data-id="picker-y"]', _picker)[0],
89
				m: $('[data-id="picker-m"]', _picker)[0],
90
				d: $('[data-id="picker-d"]', _picker)[0],
91
				h: $('[data-id="picker-h"]', _picker)[0],
92
				i: $('[data-id="picker-i"]', _picker)[0],
93
				labels: $('[data-id*="title-"]', _picker),
94
			};
95
			ui.cancel.addEventListener('tap', function() {
96
				self.hide();
97
			}, false);
98
			ui.ok.addEventListener('tap', function() {
99
				var rs = self.callback(self.getSelected());
100
				if (rs !== false) {
101
					self.hide();
102
				}
103
			}, false);
104
			ui.y.addEventListener('change', function(e) { //目前的change事件容易导致级联触发
105
			
106
				if (self.options.beginMonth || self.options.endMonth || self.options.hasToCurr) {
107
					self._createMonth();
108
				} else {
109
					self._createDay();
110
				}
111
			}, false);
112
			ui.m.addEventListener('change', function(e) {
113
				self._createDay();
114
			}, false);
115
			ui.d.addEventListener('change', function(e) {
116
				if (self.options.beginMonth || self.options.endMonth) { //仅提供了beginDate时,触发day,hours,minutes的change
117
					self._createHours();
118
				}
119
			}, false);
120
			ui.h.addEventListener('change', function(e) {
121
				if (self.options.beginMonth || self.options.endMonth) {
122
					self._createMinutes();
123
				}
124
			}, false);
125
			ui.mask[0].addEventListener('tap', function() {
126
				self.hide();
127
			}, false);
128
			self._create(options);
129
			//防止滚动穿透
130
			self.ui.picker.addEventListener($.EVENT_START, function(event) {
131
				event.preventDefault();
132
			}, false);
133
			self.ui.picker.addEventListener($.EVENT_MOVE, function(event) {
134
				event.preventDefault();
135
			}, false);
136
		},
137
		getSelected: function() {
138
			var self = this;
139
			var ui = self.ui;
140
			var type = self.options.type;
141
			
142
			var selected = {
143
				type: type,
144
				y: ui.y.picker.getSelectedItem(),
145
				m: ui.m.picker.getSelectedItem(),
146
				d: ui.d.picker.getSelectedItem(),
147
				h: ui.h.picker.getSelectedItem(),
148
				i: ui.i.picker.getSelectedItem(),
149
				toString: function() {
150
					return this.value;
151
				}
152
			};	
153
			switch (type) {
154
				case 'datetime':
155
					selected.value = selected.y.value + '-' + selected.m.value + '-' + selected.d.value + ' ' + selected.h.value + ':' + selected.i.value;
156
					selected.text = selected.y.text + '-' + selected.m.text + '-' + selected.d.text + ' ' + selected.h.text + ':' + selected.i.text;
157
					break;
158
				case 'date':
159
					selected.value = selected.y.value + '-' + selected.m.value + '-' + selected.d.value;
160
					selected.text = selected.y.text + '-' + selected.m.text + '-' + selected.d.text;
161
					break;
162
				case 'time':
163
					selected.value = selected.h.value + ':' + selected.i.value;
164
					selected.text = selected.h.text + ':' + selected.i.text;
165
					break;
166
				case 'month':
167
					if(selected.y.value=="9999") {
168
						selected.value = selected.y.value 
169
						selected.text = selected.y.text 
170
					}else {
171
						selected.value = selected.y.value + '-' + selected.m.value;
172
					selected.text = selected.y.text + '-' + selected.m.text;
173
					}
174
					
175
					break;
176
				case 'hour':
177
					selected.value = selected.y.value + '-' + selected.m.value + '-' + selected.d.value + ' ' + selected.h.value;
178
					selected.text = selected.y.text + '-' + selected.m.text + '-' + selected.d.text + ' ' + selected.h.text;
179
					break;
180
			}
181
			return selected;
182
		},
183
		setSelectedValue: function(value) {
184
			var self = this;
185
			var ui = self.ui;
186
			var parsedValue = self._parseValue(value);
187
			//TODO 嵌套过多,因为picker的change时间是异步(考虑到性能)的,所以为了保证change之后再setSelected,目前使用回调处理
188
			ui.y.picker.setSelectedValue(parsedValue.y, 0, function() {
189
				ui.m.picker.setSelectedValue(parsedValue.m, 0, function() {
190
					ui.d.picker.setSelectedValue(parsedValue.d, 0, function() {
191
						ui.h.picker.setSelectedValue(parsedValue.h, 0, function() {
192
							ui.i.picker.setSelectedValue(parsedValue.i, 0);
193
						});
194
					});
195
				});
196
			});
197
		},
198
		isLeapYear: function(year) {
199
			return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
200
		},
201
		_inArray: function(array, item) {
202
			for (var index in array) {
203
				var _item = array[index];
204
				if (_item === item) return true;
205
			}
206
			return false;
207
		},
208
		getDayNum: function(year, month) {
209
			var self = this;
210
			if (self._inArray([1, 3, 5, 7, 8, 10, 12], month)) {
211
				return 31;
212
			} else if (self._inArray([4, 6, 9, 11], month)) {
213
				return 30;
214
			} else if (self.isLeapYear(year)) {
215
				return 29;
216
			} else {
217
				return 28;
218
			}
219
		},
220
		_fill: function(num) {
221
			num = num.toString();
222
			if (num.length < 2) {
223
				num = 0 + num;
224
			}
225
			return num;
226
		},
227
		_isBeginYear: function() {
228
			return this.options.beginYear === parseInt(this.ui.y.picker.getSelectedValue());
229
		},
230
		_isBeginMonth: function() {
231
			return this.options.beginMonth && this._isBeginYear() && this.options.beginMonth === parseInt(this.ui.m.picker.getSelectedValue());
232
		},
233
		_isBeginDay: function() {
234
			return this._isBeginMonth() && this.options.beginDay === parseInt(this.ui.d.picker.getSelectedValue());
235
		},
236
		_isBeginHours: function() {
237
			return this._isBeginDay() && this.options.beginHours === parseInt(this.ui.h.picker.getSelectedValue());
238
		},
239
		_isEndYear: function() {
240
			return this.options.endYear === parseInt(this.ui.y.picker.getSelectedValue());
241
		},
242
		_isEndMonth: function() {
243
			return this.options.endMonth && this._isEndYear() && this.options.endMonth === parseInt(this.ui.m.picker.getSelectedValue());
244
		},
245
		_isEndDay: function() {
246
			return this._isEndMonth() && this.options.endDay === parseInt(this.ui.d.picker.getSelectedValue());
247
		},
248
		_isEndHours: function() {
249
			return this._isEndDay() && this.options.endHours === parseInt(this.ui.h.picker.getSelectedValue());
250
		},
251
		_createYear: function(current) {
252
			var self = this;
253
			var options = self.options;
254
			var ui = self.ui;
255
			//生成年列表
256
			var yArray = [];
257
			if (options.customData.y) {
258
				yArray = options.customData.y;
259
			} else {
260
				var yBegin = options.beginYear;
261
				var yEnd = options.endYear;
262
				for (var y = yBegin; y <= yEnd; y++) {
263
					yArray.push({
264
						text: y + '',
265
						value: y
266
					});
267
				}
268
				if(options.hasToCurr)
269
				yArray.push({
270
						text: "至今",
271
						value:9999
272
					});
273
			}
274
			ui.y.picker.setItems(yArray);
275
			//ui.y.picker.setSelectedValue(current);
276
		},
277
		_createMonth: function(current) {
278
			
279
            console.log("y change")
280
			var self = this;
281
			var options = self.options;
282
			var ui = self.ui;
283
284
			//生成月列表
285
			var mArray = [];
286
			if (options.customData.m) {
287
				mArray = options.customData.m;
288
			} else {
289
				if(this.ui.y.picker.getSelectedValue()===9999 && options.hasToCurr){}else{
290
					var m = options.beginMonth && self._isBeginYear() ? options.beginMonth : 1;
291
					var maxMonth = options.endMonth && self._isEndYear() ? options.endMonth : 12;
292
					for (; m <= maxMonth; m++) {
293
						var val = self._fill(m);
294
						mArray.push({
295
							text: val,
296
							value: val
297
						});
298
					}
299
				}
300
			}
301
			ui.m.picker.setItems(mArray);
302
			//ui.m.picker.setSelectedValue(current);
303
		},
304
		_createDay: function(current) {
305
			var self = this;
306
			var options = self.options;
307
			var ui = self.ui;
308
309
			//生成日列表
310
			var dArray = [];
311
			if (options.customData.d) {
312
				dArray = options.customData.d;
313
			} else {
314
				var d = self._isBeginMonth() ? options.beginDay : 1;
315
				var maxDay = self._isEndMonth() ? options.endDay : self.getDayNum(parseInt(this.ui.y.picker.getSelectedValue()), parseInt(this.ui.m.picker.getSelectedValue()));
316
				for (; d <= maxDay; d++) {
317
					var val = self._fill(d);
318
					dArray.push({
319
						text: val,
320
						value: val
321
					});
322
				}
323
			}
324
			ui.d.picker.setItems(dArray);
325
			current = current || ui.d.picker.getSelectedValue();
326
			//ui.d.picker.setSelectedValue(current);
327
		},
328
		_createHours: function(current) {
329
			var self = this;
330
			var options = self.options;
331
			var ui = self.ui;
332
			//生成时列表
333
			var hArray = [];
334
			if (options.customData.h) {
335
				hArray = options.customData.h;
336
			} else {
337
				var h = self._isBeginDay() ? options.beginHours : 0;
338
				var maxHours = self._isEndDay() ? options.endHours : 23;
339
				for (; h <= maxHours; h++) {
340
					var val = self._fill(h);
341
					hArray.push({
342
						text: val,
343
						value: val
344
					});
345
				}
346
			}
347
			ui.h.picker.setItems(hArray);
348
			//ui.h.picker.setSelectedValue(current);
349
		},
350
		_createMinutes: function(current) {
351
			var self = this;
352
			var options = self.options;
353
			var ui = self.ui;
354
355
			//生成分列表
356
			var iArray = [];
357
			if (options.customData.i) {
358
				iArray = options.customData.i;
359
			} else {
360
				var i = self._isBeginHours() ? options.beginMinutes : 0;
361
				var maxMinutes = self._isEndHours() ? options.endMinutes : 59;
362
				for (; i <= maxMinutes; i++) {
363
					var val = self._fill(i);
364
					iArray.push({
365
						text: val,
366
						value: val
367
					});
368
				}
369
			}
370
			ui.i.picker.setItems(iArray);
371
			//ui.i.picker.setSelectedValue(current);
372
		},
373
		_setLabels: function() {
374
			var self = this;
375
			var options = self.options;
376
			var ui = self.ui;
377
			ui.labels.each(function(i, label) {
378
				label.innerText = options.labels[i];
379
			});
380
		},
381
		_setButtons: function() {
382
			var self = this;
383
			var options = self.options;
384
			var ui = self.ui;
385
			ui.cancel.innerText = options.buttons[0];
386
			ui.ok.innerText = options.buttons[1];
387
		},
388
		_parseValue: function(value) {
389
			var self = this;
390
			var rs = {};
391
			if (value) {
392
				var parts = value.replace(":", "-").replace(" ", "-").split("-");
393
				rs.y = parts[0];
394
				rs.m = parts[1];
395
				rs.d = parts[2];
396
				rs.h = parts[3];
397
				rs.i = parts[4];
398
			} else {
399
				var now = new Date();
400
				rs.y = now.getFullYear();
401
				rs.m = now.getMonth() + 1;
402
				rs.d = now.getDate();
403
				rs.h = now.getHours();
404
				rs.i = now.getMinutes();
405
			}
406
			return rs;
407
		},
408
		_create: function(options) {
409
			var self = this;
410
			options = options || {};
411
			options.labels = options.labels || ['年', '月', '日', '时', '分'];
412
			options.buttons = options.buttons || ['取消', '确定'];
413
			options.type = options.type || 'datetime';
414
			options.customData = options.customData || {};
415
			self.options = options;
416
			var now = new Date();
417
			var beginDate = options.beginDate;
418
			if (beginDate instanceof Date && !isNaN(beginDate.valueOf())) { //设定了开始日期
419
				options.beginYear = beginDate.getFullYear();
420
				options.beginMonth = beginDate.getMonth() + 1;
421
				options.beginDay = beginDate.getDate();
422
				options.beginHours = beginDate.getHours();
423
				options.beginMinutes = beginDate.getMinutes();
424
			}
425
			var endDate = options.endDate;
426
			if (endDate instanceof Date && !isNaN(endDate.valueOf())) { //设定了结束日期
427
				options.endYear = endDate.getFullYear();
428
				options.endMonth = endDate.getMonth() + 1;
429
				options.endDay = endDate.getDate();
430
				options.endHours = endDate.getHours();
431
				options.endMinutes = endDate.getMinutes();
432
			}
433
			options.beginYear = options.beginYear || (now.getFullYear() - 5);
434
			options.endYear = options.endYear || (now.getFullYear() + 5);
435
			var ui = self.ui;
436
			//设定label
437
			self._setLabels();
438
			self._setButtons();
439
			//设定类型
440
			ui.picker.setAttribute('data-type', options.type);
441
			//生成
442
			self._createYear();
443
			self._createMonth();
444
			self._createDay();
445
			self._createHours();
446
			self._createMinutes();
447
			//设定默认值
448
			self.setSelectedValue(options.value);
449
		},
450
		//显示
451
		show: function(callback) {
452
			var self = this;
453
			var ui = self.ui;
454
			self.callback = callback || $.noop;
455
			ui.mask.show();
456
			document.body.classList.add($.className('dtpicker-active-for-page'));
457
			ui.picker.classList.add($.className('active'));
458
			//处理物理返回键
459
			self.__back = $.back;
460
			$.back = function() {
461
				self.hide();
462
			};
463
		},
464
		hide: function() {
465
			var self = this;
466
			if (self.disposed) return;
467
			var ui = self.ui;
468
			ui.picker.classList.remove($.className('active'));
469
			ui.mask.close();
470
			document.body.classList.remove($.className('dtpicker-active-for-page'));
471
			//处理物理返回键
472
			$.back = self.__back;
473
		},
474
		dispose: function() {
475
			var self = this;
476
			self.hide();
477
			setTimeout(function() {
478
				self.ui.picker.parentNode.removeChild(self.ui.picker);
479
				for (var name in self) {
480
					self[name] = null;
481
					delete self[name];
482
				};
483
				self.disposed = true;
484
			}, 300);
485
		}
486
	});
487
488
})(mui, document);

+ 389 - 0
app/js/public/mui.picker.js

@ -0,0 +1,389 @@
1
/**
2
 * 选择列表插件
3
 * varstion 2.0.0
4
 * by Houfeng
5
 * Houfeng@DCloud.io
6
 */
7
8
(function($, window, document, undefined) {
9
10
	var MAX_EXCEED = 30;
11
	var VISIBLE_RANGE = 90;
12
	var DEFAULT_ITEM_HEIGHT = 40;
13
	var BLUR_WIDTH = 10;
14
15
	var rad2deg = $.rad2deg = function(rad) {
16
		return rad / (Math.PI / 180);
17
	};
18
19
	var deg2rad = $.deg2rad = function(deg) {
20
		return deg * (Math.PI / 180);
21
	};
22
23
	var platform = navigator.platform.toLowerCase();
24
	var userAgent = navigator.userAgent.toLowerCase();
25
	var isIos = (userAgent.indexOf('iphone') > -1 ||
26
			userAgent.indexOf('ipad') > -1 ||
27
			userAgent.indexOf('ipod') > -1) &&
28
		(platform.indexOf('iphone') > -1 ||
29
			platform.indexOf('ipad') > -1 ||
30
			platform.indexOf('ipod') > -1);
31
	//alert(isIos);
32
33
	var Picker = $.Picker = function(holder, options) {
34
		var self = this;
35
		self.holder = holder;
36
		self.options = options || {};
37
		self.init();
38
		self.initInertiaParams();
39
		self.calcElementItemPostion(true);
40
		self.bindEvent();
41
	};
42
43
	Picker.prototype.findElementItems = function() {
44
		var self = this;
45
		self.elementItems = [].slice.call(self.holder.querySelectorAll('li'));
46
		return self.elementItems;
47
	};
48
49
	Picker.prototype.init = function() {
50
		var self = this;
51
		self.list = self.holder.querySelector('ul');
52
		self.findElementItems();
53
		self.height = self.holder.offsetHeight;
54
		self.r = self.height / 2 - BLUR_WIDTH;
55
		self.d = self.r * 2;
56
		self.itemHeight = self.elementItems.length > 0 ? self.elementItems[0].offsetHeight : DEFAULT_ITEM_HEIGHT;
57
		self.itemAngle = parseInt(self.calcAngle(self.itemHeight * 0.8));
58
		self.hightlightRange = self.itemAngle / 2;
59
		self.visibleRange = VISIBLE_RANGE;
60
		self.beginAngle = 0;
61
		self.beginExceed = self.beginAngle - MAX_EXCEED;
62
		self.list.angle = self.beginAngle;
63
		if (isIos) {
64
			self.list.style.webkitTransformOrigin = "center center " + self.r + "px";
65
		}
66
	};
67
68
	Picker.prototype.calcElementItemPostion = function(andGenerateItms) {
69
		var self = this;
70
		if (andGenerateItms) {
71
			self.items = [];
72
		}
73
		self.elementItems.forEach(function(item) {
74
			var index = self.elementItems.indexOf(item);
75
			self.endAngle = self.itemAngle * index;
76
			item.angle = self.endAngle;
77
			item.style.webkitTransformOrigin = "center center -" + self.r + "px";
78
			item.style.webkitTransform = "translateZ(" + self.r + "px) rotateX(" + (-self.endAngle) + "deg)";
79
			if (andGenerateItms) {
80
				var dataItem = {};
81
				dataItem.text = item.innerHTML || '';
82
				dataItem.value = item.getAttribute('data-value') || dataItem.text;
83
				self.items.push(dataItem);
84
			}
85
		});
86
		self.endExceed = self.endAngle + MAX_EXCEED;
87
		self.calcElementItemVisibility(self.beginAngle);
88
	};
89
90
	Picker.prototype.calcAngle = function(c) {
91
		var self = this;
92
		var a = b = parseFloat(self.r);
93
		//直径的整倍数部分直接乘以 180
94
		c = Math.abs(c); //只算角度不关心正否值
95
		var intDeg = parseInt(c / self.d) * 180;
96
		c = c % self.d;
97
		//余弦
98
		var cosC = (a * a + b * b - c * c) / (2 * a * b);
99
		var angleC = intDeg + rad2deg(Math.acos(cosC));
100
		return angleC;
101
	};
102
103
	Picker.prototype.calcElementItemVisibility = function(angle) {
104
		var self = this;
105
		self.elementItems.forEach(function(item) {
106
			var difference = Math.abs(item.angle - angle);
107
			if (difference < self.hightlightRange) {
108
				item.classList.add('highlight');
109
			} else if (difference < self.visibleRange) {
110
				item.classList.add('visible');
111
				item.classList.remove('highlight');
112
			} else {
113
				item.classList.remove('highlight');
114
				item.classList.remove('visible');
115
			}
116
		});
117
	};
118
119
	Picker.prototype.setAngle = function(angle) {
120
		var self = this;
121
		self.list.angle = angle;
122
		self.list.style.webkitTransform = "perspective(1000px) rotateY(0deg) rotateX(" + angle + "deg)";
123
		self.calcElementItemVisibility(angle);
124
	};
125
126
	Picker.prototype.bindEvent = function() {
127
		var self = this;
128
		var lastAngle = 0;
129
		var startY = null;
130
		var isPicking = false;
131
		self.holder.addEventListener($.EVENT_START, function(event) {
132
			isPicking = true;
133
			event.preventDefault();
134
			self.list.style.webkitTransition = '';
135
			startY = (event.changedTouches ? event.changedTouches[0] : event).pageY;
136
			lastAngle = self.list.angle;
137
			self.updateInertiaParams(event, true);
138
		}, false);
139
		self.holder.addEventListener($.EVENT_END, function(event) {
140
			isPicking = false;
141
			event.preventDefault();
142
			self.startInertiaScroll(event);
143
		}, false);
144
		self.holder.addEventListener($.EVENT_CANCEL, function(event) {
145
			isPicking = false;
146
			event.preventDefault();
147
			self.startInertiaScroll(event);
148
		}, false);
149
		self.holder.addEventListener($.EVENT_MOVE, function(event) {
150
			if (!isPicking) {
151
				return;
152
			}
153
			event.preventDefault();
154
			var endY = (event.changedTouches ? event.changedTouches[0] : event).pageY;
155
			var dragRange = endY - startY;
156
			var dragAngle = self.calcAngle(dragRange);
157
			var newAngle = dragRange > 0 ? lastAngle - dragAngle : lastAngle + dragAngle;
158
			if (newAngle > self.endExceed) {
159
				newAngle = self.endExceed
160
			}
161
			if (newAngle < self.beginExceed) {
162
				newAngle = self.beginExceed
163
			}
164
			self.setAngle(newAngle);
165
			self.updateInertiaParams(event);
166
		}, false);
167
		//--
168
		self.list.addEventListener('tap', function(event) {
169
			elementItem = event.target;
170
			if (elementItem.tagName == 'LI') {
171
				self.setSelectedIndex(self.elementItems.indexOf(elementItem), 200);
172
			}
173
		}, false);
174
	};
175
176
	Picker.prototype.initInertiaParams = function() {
177
		var self = this;
178
		self.lastMoveTime = 0;
179
		self.lastMoveStart = 0;
180
		self.stopInertiaMove = false;
181
	};
182
183
	Picker.prototype.updateInertiaParams = function(event, isStart) {
184
		var self = this;
185
		var point = event.changedTouches ? event.changedTouches[0] : event;
186
		if (isStart) {
187
			self.lastMoveStart = point.pageY;
188
			self.lastMoveTime = event.timeStamp || Date.now();
189
			self.startAngle = self.list.angle;
190
		} else {
191
			var nowTime = event.timeStamp || Date.now();
192
			if (nowTime - self.lastMoveTime > 300) {
193
				self.lastMoveTime = nowTime;
194
				self.lastMoveStart = point.pageY;
195
			}
196
		}
197
		self.stopInertiaMove = true;
198
	};
199
200
	Picker.prototype.startInertiaScroll = function(event) {
201
		var self = this;
202
		var point = event.changedTouches ? event.changedTouches[0] : event;
203
		/** 
204
		 * 缓动代码
205
		 */
206
		var nowTime = event.timeStamp || Date.now();
207
		var v = (point.pageY - self.lastMoveStart) / (nowTime - self.lastMoveTime); //最后一段时间手指划动速度  
208
		var dir = v > 0 ? -1 : 1; //加速度方向  
209
		var deceleration = dir * 0.0006 * -1;
210
		var duration = Math.abs(v / deceleration); // 速度消减至0所需时间  
211
		var dist = v * duration / 2; //最终移动多少 
212
		var startAngle = self.list.angle;
213
		var distAngle = self.calcAngle(dist) * dir;
214
		//----
215
		var srcDistAngle = distAngle;
216
		if (startAngle + distAngle < self.beginExceed) {
217
			distAngle = self.beginExceed - startAngle;
218
			duration = duration * (distAngle / srcDistAngle) * 0.6;
219
		}
220
		if (startAngle + distAngle > self.endExceed) {
221
			distAngle = self.endExceed - startAngle;
222
			duration = duration * (distAngle / srcDistAngle) * 0.6;
223
		}
224
		//----
225
		if (distAngle == 0) {
226
			self.endScroll();
227
			return;
228
		}
229
		self.scrollDistAngle(nowTime, startAngle, distAngle, duration);
230
	};
231
232
	Picker.prototype.scrollDistAngle = function(nowTime, startAngle, distAngle, duration) {
233
		var self = this;
234
		self.stopInertiaMove = false;
235
		(function(nowTime, startAngle, distAngle, duration) {
236
			var frameInterval = 13;
237
			var stepCount = duration / frameInterval;
238
			var stepIndex = 0;
239
			(function inertiaMove() {
240
				if (self.stopInertiaMove) return;
241
				var newAngle = self.quartEaseOut(stepIndex, startAngle, distAngle, stepCount);
242
				self.setAngle(newAngle);
243
				stepIndex++;
244
				if (stepIndex > stepCount - 1 || newAngle < self.beginExceed || newAngle > self.endExceed) {
245
					self.endScroll();
246
					return;
247
				}
248
				setTimeout(inertiaMove, frameInterval);
249
			})();
250
		})(nowTime, startAngle, distAngle, duration);
251
	};
252
253
	Picker.prototype.quartEaseOut = function(t, b, c, d) {
254
		return -c * ((t = t / d - 1) * t * t * t - 1) + b;
255
	};
256
257
	Picker.prototype.endScroll = function() {
258
		var self = this;
259
		if (self.list.angle < self.beginAngle) {
260
			self.list.style.webkitTransition = "150ms ease-out";
261
			self.setAngle(self.beginAngle);
262
		} else if (self.list.angle > self.endAngle) {
263
			self.list.style.webkitTransition = "150ms ease-out";
264
			self.setAngle(self.endAngle);
265
		} else {
266
			var index = parseInt((self.list.angle / self.itemAngle).toFixed(0));
267
			self.list.style.webkitTransition = "100ms ease-out";
268
			self.setAngle(self.itemAngle * index);
269
		}
270
		self.triggerChange();
271
	};
272
273
	Picker.prototype.triggerChange = function(force) {
274
		var self = this;
275
		setTimeout(function() {
276
			var index = self.getSelectedIndex();
277
			var item = self.items[index];
278
			if ($.trigger && (index != self.lastIndex || force === true)) {
279
				$.trigger(self.holder, 'change', {
280
					"index": index,
281
					"item": item
282
				});
283
				//console.log('change:' + index);
284
			}
285
			self.lastIndex = index;
286
			typeof force === 'function' && force();
287
		}, 0);
288
	};
289
290
	Picker.prototype.correctAngle = function(angle) {
291
		var self = this;
292
		if (angle < self.beginAngle) {
293
			return self.beginAngle;
294
		} else if (angle > self.endAngle) {
295
			return self.endAngle;
296
		} else {
297
			return angle;
298
		}
299
	};
300
301
	Picker.prototype.setItems = function(items) {
302
		var self = this;
303
		self.items = items || [];
304
		var buffer = [];
305
		self.items.forEach(function(item) {
306
			if (item !== null && item !== undefined) {
307
				buffer.push('<li>' + (item.text || item) + '</li>');
308
			}
309
		});
310
		self.list.innerHTML = buffer.join('');
311
		self.findElementItems();
312
		self.calcElementItemPostion();
313
		self.setAngle(self.correctAngle(self.list.angle));
314
		self.triggerChange(true);
315
	};
316
317
	Picker.prototype.getItems = function() {
318
		var self = this;
319
		return self.items;
320
	};
321
322
	Picker.prototype.getSelectedIndex = function() {
323
		var self = this;
324
		return parseInt((self.list.angle / self.itemAngle).toFixed(0));
325
	};
326
327
	Picker.prototype.setSelectedIndex = function(index, duration, callback) {
328
		var self = this;
329
		self.list.style.webkitTransition = '';
330
		var angle = self.correctAngle(self.itemAngle * index);
331
		if (duration && duration > 0) {
332
			var distAngle = angle - self.list.angle;
333
			self.scrollDistAngle(Date.now(), self.list.angle, distAngle, duration);
334
		} else {
335
			self.setAngle(angle);
336
		}
337
		self.triggerChange(callback);
338
	};
339
340
	Picker.prototype.getSelectedItem = function() {
341
		var self = this;
342
		return self.items[self.getSelectedIndex()];
343
	};
344
345
	Picker.prototype.getSelectedValue = function() {
346
		var self = this;
347
		return (self.items[self.getSelectedIndex()] || {}).value;
348
	};
349
350
	Picker.prototype.getSelectedText = function() {
351
		var self = this;
352
		return (self.items[self.getSelectedIndex()] || {}).text;
353
	};
354
355
	Picker.prototype.setSelectedValue = function(value, duration, callback) {
356
		var self = this;
357
		for (var index in self.items) {
358
			var item = self.items[index];
359
			if (item.value == value) {
360
				self.setSelectedIndex(index, duration, callback);
361
				return;
362
			}
363
		}
364
	};
365
366
	if ($.fn) {
367
		$.fn.picker = function(options) {
368
			//遍历选择的元素
369
			this.each(function(i, element) {
370
				if (element.picker) return;
371
				if (options) {
372
					element.picker = new Picker(element, options);
373
				} else {
374
					var optionsText = element.getAttribute('data-picker-options');
375
					var _options = optionsText ? JSON.parse(optionsText) : {};
376
					element.picker = new Picker(element, _options);
377
				}
378
			});
379
			return this[0] ? this[0].picker : null;
380
		};
381
382
		//自动初始化
383
		$.ready(function() {
384
			$('.mui-picker').picker();
385
		});
386
	}
387
388
})(window.mui || window, window, document, undefined);
389
//end