├── .gitignore
├── .babelrc
├── lib
├── images
│ └── show.png
├── js
│ ├── poppicker.js
│ ├── picker.js
│ └── dtpicker.js
└── css
│ └── picker.css
├── src
├── images
│ └── show.png
├── DatePicker.js
├── CityPicker.js
├── js
│ ├── poppicker.js
│ ├── picker.js
│ ├── dtpicker.js
│ └── mui.js
└── css
│ └── picker.css
├── example
├── server.js
├── webpack.config.example.js
├── index.html
├── src
│ └── index.js
└── lib
│ └── city-data.js
├── index.js
├── webpack.config.js
├── package.json
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["react", "es2015", "stage-0"]
3 | }
4 |
--------------------------------------------------------------------------------
/lib/images/show.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/petitspois/react-picker/HEAD/lib/images/show.png
--------------------------------------------------------------------------------
/src/images/show.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/petitspois/react-picker/HEAD/src/images/show.png
--------------------------------------------------------------------------------
/example/server.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 | var WebpackDevServer = require('webpack-dev-server');
3 | var config = require('./webpack.config.example');
4 | var port = 8080;
5 | var options = {
6 | publicPath: config.output.publicPath
7 | };
8 |
9 |
10 |
11 | var server = new WebpackDevServer(webpack(config), options);
12 | server.listen(port, '0.0.0.0', function (err, result) {
13 | if (err) console.error(err);
14 | console.log('Listening at localhost:%s', port);
15 | });
16 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.CityPicker = exports.DatePicker = undefined;
7 |
8 | var _datepicker = require('./lib/datepicker');
9 |
10 | var _datepicker2 = _interopRequireDefault(_datepicker);
11 |
12 | var _citypicker = require('./lib/citypicker');
13 |
14 | var _citypicker2 = _interopRequireDefault(_citypicker);
15 |
16 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17 |
18 | exports.DatePicker = _datepicker2.default;
19 | exports.CityPicker = _citypicker2.default;
20 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var node_modules = path.resolve(__dirname, 'node_modules');
3 | var webpack = require('webpack');
4 |
5 | module.exports = {
6 | devtool: 'eval-source-map',
7 | entry: {
8 | datepicker: './src/DatePicker',
9 | citypicker: './src/CityPicker'
10 | },
11 | output: {
12 | path: path.join(__dirname, '/lib'),
13 | libraryTarget: 'umd',
14 | filename: '[name].js'
15 | },
16 | module: {
17 | loaders: [{
18 | test: /\.js$/,
19 | exclude: /node_modules/,
20 | loaders: ['babel-loader']
21 | }, {
22 | test: /\.css$/,
23 | exclude: path.join(__dirname, 'src'),
24 | loader: 'style!css'
25 | }]
26 | },
27 | devServer: {
28 | contentBase: path.join(__dirname, 'example')
29 | }
30 | };
31 |
--------------------------------------------------------------------------------
/example/webpack.config.example.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var node_modules = path.resolve(__dirname, 'node_modules');
3 | var lib = path.resolve(__dirname, 'lib');
4 | var webpack = require('webpack');
5 |
6 | module.exports = {
7 | entry: {
8 | app:[
9 | 'webpack-dev-server/client?http://0.0.0.0:7000',
10 | './src/index'
11 | ]
12 | },
13 | output: {
14 | path:path.join(__dirname, '/lib'),
15 | filename: 'app.js',
16 | publicPath: '/lib/'
17 | },
18 | module: {
19 | loaders: [{
20 | test: /\.js$/,
21 | exclude: [/node_modules/, /lib/],
22 | loaders: [ 'babel-loader' ]
23 | },
24 | {
25 | test: /\.css$/,
26 | exclude: path.join(__dirname, 'src'),
27 | loader: 'style!css'
28 | }
29 | ]
30 | },
31 | resolve: {
32 | alias: {
33 | 'react-picker': path.join(__dirname, '..', 'index.js')
34 | }
35 | }
36 | };
37 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-pickers",
3 | "version": "0.1.0",
4 | "description": "datapicker and citypicker base on MUI of picker",
5 | "main": "/index.js",
6 | "repository": "petitspois/react-picker",
7 | "homepage": "https://github.com/petitspois/react-picker#readme",
8 | "bugs": "https://github.com/petitspois/react-picker/issues",
9 | "scripts": {
10 | "start": "node server.js",
11 | "build": "./node_modules/.bin/babel src --copy-files --extensions .js --out-dir lib",
12 | "clean": "rm -rf ./lib/*",
13 | "test": "echo \"Error: no test specified\" && exit 1"
14 | },
15 | "keywords": [
16 | "react",
17 | "datapicker",
18 | "citypicker",
19 | "mui"
20 | ],
21 | "license": "MIT",
22 | "author": "petitspois",
23 | "dependencies": {
24 | "css-loader": "^0.23.1",
25 | "react": "^15.1.0",
26 | "react-dom": "^15.1.0",
27 | "style-loader": "^0.13.1"
28 | },
29 | "devDependencies": {
30 | "babel-cli": "^6.11.4",
31 | "babel-core": "^6.9.1",
32 | "babel-loader": "^6.2.4",
33 | "babel-polyfill": "^6.9.1",
34 | "babel-preset-es2015": "^6.9.0",
35 | "babel-preset-react": "^6.5.0",
36 | "babel-preset-stage-0": "^6.5.0",
37 | "webpack": "^1.13.1",
38 | "webpack-dev-server": "^1.14.1"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | react-picker example
7 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/src/DatePicker.js:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react'
2 |
3 | import './js/mui'
4 | import './js/picker'
5 | import DtPicker from './js/dtpicker'
6 |
7 | class DatePicker extends Component{
8 |
9 | static defalutProps = {
10 | visible: false,
11 | options: {}
12 | };
13 |
14 | static propTypes = {
15 | visible: PropTypes.bool,
16 | getData: PropTypes.func,
17 | confirm: PropTypes.func,
18 | cancel: PropTypes.func,
19 | options: PropTypes.object
20 | };
21 |
22 | constructor(props){
23 | super(props)
24 | this.userPicker = {};
25 | }
26 |
27 | componentDidMount(){
28 | this.userPicker = new DtPicker(this.props.options);
29 | this.userPicker.ui.cancel.addEventListener('tap', event => {
30 | this.props.cancel();
31 | }, false);
32 | this.userPicker.ui.mask[0].addEventListener('tap', () => {
33 | this.props.cancel();
34 | }, false);
35 | }
36 |
37 | show(){
38 | this.userPicker.show(items => {
39 | this.props.getData(items.text);
40 | this.props.cancel && this.props.cancel();
41 | })
42 | }
43 |
44 | componentDidUpdate(){
45 | if(this.props.visible){
46 | this.show()
47 | }else{
48 | this.userPicker.hide();
49 | }
50 | }
51 |
52 | render(){
53 | return(
54 |
55 | )
56 | }
57 | }
58 |
59 | export default DatePicker
60 |
--------------------------------------------------------------------------------
/src/CityPicker.js:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react'
2 |
3 | import './js/mui'
4 | import './js/picker'
5 | import PopPicker from './js/poppicker'
6 |
7 | class CityPicker extends Component{
8 |
9 | static defalutProps = {
10 | visible: false
11 | };
12 |
13 | static propTypes = {
14 | visible: PropTypes.bool,
15 | setData: PropTypes.array,
16 | getData: PropTypes.func,
17 | confirm: PropTypes.func,
18 | cancel: PropTypes.func
19 | };
20 |
21 | constructor(props){
22 | super(props)
23 | this.userPicker = {};
24 | }
25 |
26 | componentDidMount(){
27 | this.userPicker = new PopPicker({layer: this.props.layer || '',defaultVal:this.props.defaultVal });
28 | this.userPicker.setData(this.props.setData);
29 | this.userPicker.cancel.addEventListener('tap', event => {
30 | this.props.cancel();
31 | }, false);
32 | this.userPicker.mask[0].addEventListener('tap', () => {
33 | this.props.cancel();
34 | }, false);
35 | }
36 |
37 | show(){
38 | this.userPicker.show(items => {
39 | this.props.getData(items);
40 | this.props.cancel && this.props.cancel();
41 | })
42 | }
43 |
44 | componentDidUpdate(){
45 | if(this.props.visible){
46 | this.show()
47 | }else{
48 | this.userPicker.hide();
49 | }
50 | }
51 |
52 | render(){
53 | return(
54 |
55 | )
56 | }
57 | }
58 |
59 | export default CityPicker
60 |
--------------------------------------------------------------------------------
/example/src/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { render } from 'react-dom';
3 |
4 | import '../../lib/css/picker.css'
5 | // import { CityPicker, DatePicker } from 'react-picker'
6 | import { CityPicker, DatePicker } from '../../'
7 |
8 |
9 | import city2 from '../lib/city-data'
10 | import city3 from '../lib/city-data-3'
11 |
12 | class App extends Component{
13 |
14 | state = {
15 | showCityPicker: false,
16 | showCity2Picker:false,
17 | showCity3Picker:false,
18 | showDatePicker:false,
19 | showDatePicker2:false,
20 | singleData : [{
21 | value: 'ywj',
22 | text: '董事长 叶文洁'
23 | }, {
24 | value: 'aaa',
25 | text: '总经理 艾AA'
26 | }, {
27 | value: 'lj',
28 | text: '罗辑'
29 | }, {
30 | value: 'ymt',
31 | text: '云天明'
32 | }, {
33 | value: 'shq',
34 | text: '史强'
35 | }, {
36 | value: 'zhbh',
37 | text: '章北海'
38 | }, {
39 | value: 'zhy',
40 | text: '庄颜'
41 | }, {
42 | value: 'gyf',
43 | text: '关一帆'
44 | }, {
45 | value: 'zhz',
46 | text: '智子'
47 | }, {
48 | value: 'gezh',
49 | text: '歌者'
50 | }],
51 | city2: city2,
52 | city3: city3
53 | }
54 |
55 | showCityPicker(){
56 | this.setState({showCityPicker: true })
57 | }
58 |
59 | showCity2Picker(){
60 | this.setState({showCity2Picker: true })
61 | }
62 |
63 | showCity3Picker(){
64 | this.setState({showCity3Picker: true })
65 | }
66 |
67 | ok(){
68 | this.setState({showCityPicker: false })
69 | }
70 |
71 | cl(){
72 | this.setState({showCityPicker: false })
73 | }
74 |
75 |
76 | ok2(){
77 | this.setState({showCity2Picker: false })
78 | }
79 |
80 | cl2(){
81 | this.setState({showCity2Picker: false })
82 | }
83 |
84 | ok3(){
85 | this.setState({showCity3Picker: false })
86 | }
87 |
88 | cl3(){
89 | this.setState({showCity3Picker: false })
90 | }
91 |
92 | ok4(){
93 | this.setState({showDatePicker: false })
94 | }
95 |
96 | cl4(){
97 | this.setState({showDatePicker: false })
98 | }
99 |
100 | ok5(){
101 | this.setState({showDatePicker2: false })
102 | }
103 |
104 | cl5(){
105 | this.setState({showDatePicker2: false })
106 | }
107 |
108 | getData(ret){
109 | console.log(ret);
110 | }
111 |
112 | getData2(ret){
113 | console.log("你选择的城市是:" + ret[0].text + " " + ret[1].text);
114 | }
115 |
116 | getData3(ret){
117 | console.log("你选择的城市是:" + (ret[0] || {}).text + " " + (ret[1] || {}).text + " " + (ret[2] || {}).text);
118 | }
119 |
120 | getData4(ret){
121 | console.log('选择结果: ' + ret);
122 | }
123 |
124 | getData5(ret){
125 | console.log('选择结果: ' + ret);
126 | }
127 |
128 | selectDate(){
129 | this.setState({showDatePicker: true })
130 | }
131 |
132 | selectDate2(){
133 | this.setState({showDatePicker2: true })
134 | }
135 |
136 | render(){
137 | return (
138 |
139 |
普通示例
140 |
141 |
142 |
级联示例
143 |
144 |
145 |
148 |
149 |
150 |
151 |
152 |
153 |
常规示例
154 |
155 |
156 | 设定年份区间
157 |
158 |
159 |
160 |
161 |
162 | )
163 | }
164 | }
165 |
166 |
167 | render(
168 | ,
169 | document.querySelector('#root')
170 | )
171 |
--------------------------------------------------------------------------------
/lib/js/poppicker.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _mui = require('./mui');
8 |
9 | var _mui2 = _interopRequireDefault(_mui);
10 |
11 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12 |
13 | (function ($, document) {
14 |
15 | //创建 DOM
16 | $.dom = function (str) {
17 | if (typeof str !== 'string') {
18 | if (str instanceof Array || str[0] && str.length) {
19 | return [].slice.call(str);
20 | } else {
21 | return [str];
22 | }
23 | }
24 | if (!$.__create_dom_div__) {
25 | $.__create_dom_div__ = document.createElement('div');
26 | }
27 | $.__create_dom_div__.innerHTML = str;
28 | return [].slice.call($.__create_dom_div__.childNodes);
29 | };
30 |
31 | var panelBuffer = '\
32 | \
37 |
\
38 |
\
39 |
';
40 |
41 | var pickerBuffer = '\
42 |
\
43 |
\
44 |
\
46 |
\
47 |
\
48 |
';
49 |
50 | //定义弹出选择器类
51 | var PopPicker = $.PopPicker = $.Class.extend({
52 | //构造函数
53 | init: function init(options) {
54 | var self = this;
55 | self.options = options || {};
56 | self.options.buttons = self.options.buttons || ['取消', '确定'];
57 | self.panel = $.dom(panelBuffer)[0];
58 | document.body.appendChild(self.panel);
59 | self.ok = self.panel.querySelector('.mui-poppicker-btn-ok');
60 | self.cancel = self.panel.querySelector('.mui-poppicker-btn-cancel');
61 | self.body = self.panel.querySelector('.mui-poppicker-body');
62 | self.mask = $.createMask();
63 | self.cancel.innerText = self.options.buttons[0];
64 | self.ok.innerText = self.options.buttons[1];
65 | self.ok.addEventListener('tap', function (event) {
66 | if (self.callback) {
67 | self.callback(self.getSelectedItems());
68 | }
69 | }, false);
70 | self._createPicker();
71 | //防止滚动穿透
72 | self.panel.addEventListener($.EVENT_START, function (event) {
73 | event.preventDefault();
74 | }, false);
75 | self.panel.addEventListener($.EVENT_MOVE, function (event) {
76 | event.preventDefault();
77 | }, false);
78 | },
79 | _createPicker: function _createPicker() {
80 | var self = this;
81 | var layer = self.options.layer || 1;
82 | var width = 100 / layer + '%';
83 | self.pickers = [];
84 | for (var i = 1; i <= layer; i++) {
85 | var pickerElement = $.dom(pickerBuffer)[0];
86 | pickerElement.style.width = width;
87 | self.body.appendChild(pickerElement);
88 | var picker = $(pickerElement).picker();
89 | self.pickers.push(picker);
90 | pickerElement.addEventListener('change', function (event) {
91 | var nextPickerElement = this.nextSibling;
92 | if (nextPickerElement && nextPickerElement.picker) {
93 | var eventData = event.detail || {};
94 | var preItem = eventData.item || {};
95 | nextPickerElement.picker.setItems(preItem.children);
96 | }
97 | }, false);
98 | }
99 | },
100 | //填充数据
101 | setData: function setData(data) {
102 | var self = this;
103 | data = data || [];
104 | self.pickers[0].setItems(data);
105 | },
106 | //获取选中的项(数组)
107 | getSelectedItems: function getSelectedItems() {
108 | var self = this;
109 | var items = [];
110 | for (var i in self.pickers) {
111 | var picker = self.pickers[i];
112 | items.push(picker.getSelectedItem() || {});
113 | }
114 | return items;
115 | },
116 | //显示
117 | show: function show(callback) {
118 | var self = this;
119 | self.callback = callback;
120 | self.mask.show();
121 | document.body.classList.add($.className('poppicker-active-for-page'));
122 | self.panel.classList.add($.className('active'));
123 | //处理物理返回键
124 | self.__back = $.back;
125 | $.back = function () {
126 | self.hide();
127 | };
128 | },
129 | //隐藏
130 | hide: function hide() {
131 | var self = this;
132 | if (self.disposed) return;
133 | self.panel.classList.remove($.className('active'));
134 | self.mask.close();
135 | document.body.classList.remove($.className('poppicker-active-for-page'));
136 | //处理物理返回键
137 | $.back = self.__back;
138 | },
139 | dispose: function dispose() {
140 | var self = this;
141 | self.hide();
142 | setTimeout(function () {
143 | self.panel.parentNode.removeChild(self.panel);
144 | for (var name in self) {
145 | self[name] = null;
146 | delete self[name];
147 | };
148 | self.disposed = true;
149 | }, 300);
150 | }
151 | });
152 | })(_mui2.default, document); /**
153 | * 弹出选择列表插件
154 | * 此组件依赖 listpcker ,请在页面中先引入 mui.picker.css + mui.picker.js
155 | * varstion 1.0.1
156 | * by Houfeng
157 | * Houfeng@DCloud.io
158 | */
159 |
160 | exports.default = _mui2.default.PopPicker;
--------------------------------------------------------------------------------
/src/js/poppicker.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 弹出选择列表插件
3 | * 此组件依赖 listpcker ,请在页面中先引入 mui.picker.css + mui.picker.js
4 | * varstion 1.0.1
5 | * by Houfeng
6 | * Houfeng@DCloud.io
7 | */
8 |
9 | import mui from './mui'
10 |
11 | (function($, document) {
12 |
13 | //创建 DOM
14 | $.dom = function(str) {
15 | if (typeof(str) !== 'string') {
16 | if ((str instanceof Array) || (str[0] && str.length)) {
17 | return [].slice.call(str);
18 | } else {
19 | return [str];
20 | }
21 | }
22 | if (!$.__create_dom_div__) {
23 | $.__create_dom_div__ = document.createElement('div');
24 | }
25 | $.__create_dom_div__.innerHTML = str;
26 | return [].slice.call($.__create_dom_div__.childNodes);
27 | };
28 |
29 | var panelBuffer = '\
30 | \
35 |
\
36 |
\
37 |
';
38 |
39 | var pickerBuffer = '\
40 |
\
41 |
\
42 |
\
44 |
\
45 |
\
46 |
';
47 |
48 | //定义弹出选择器类
49 | var PopPicker = $.PopPicker = $.Class.extend({
50 | //构造函数
51 | init: function(options) {
52 | var self = this;
53 | self.options = options || {};
54 | self.options.buttons = self.options.buttons || ['取消', '确定'];
55 | self.panel = $.dom(panelBuffer)[0];
56 | document.body.appendChild(self.panel);
57 | self.ok = self.panel.querySelector('.mui-poppicker-btn-ok');
58 | self.cancel = self.panel.querySelector('.mui-poppicker-btn-cancel');
59 | self.body = self.panel.querySelector('.mui-poppicker-body');
60 | self.mask = $.createMask();
61 | self.cancel.innerText = self.options.buttons[0];
62 | self.ok.innerText = self.options.buttons[1];
63 | self.ok.addEventListener('tap', function(event) {
64 | if (self.callback) {
65 | self.callback(self.getSelectedItems());
66 | }
67 | }, false);
68 | self._createPicker();
69 | //防止滚动穿透
70 | self.panel.addEventListener($.EVENT_START, function(event) {
71 | event.preventDefault();
72 | }, false);
73 | self.panel.addEventListener($.EVENT_MOVE, function(event) {
74 | event.preventDefault();
75 | }, false);
76 | },
77 | _createPicker: function() {
78 | var self = this;
79 | var layer = self.options.layer || 1;
80 | var width = (100 / layer) + '%';
81 | self.pickers = [];
82 | for (var i = 1; i <= layer; i++) {
83 | var pickerElement = $.dom(pickerBuffer)[0];
84 | pickerElement.style.width = width;
85 | self.body.appendChild(pickerElement);
86 | var picker = $(pickerElement).picker();
87 | self.pickers.push(picker);
88 | pickerElement.addEventListener('change', function(event) {
89 | var nextPickerElement = this.nextSibling;
90 | if (nextPickerElement && nextPickerElement.picker) {
91 | var eventData = event.detail || {};
92 | var preItem = eventData.item || {};
93 | nextPickerElement.picker.setItems(preItem.children);
94 | }
95 | }, false);
96 | }
97 |
98 | //等选择数据初始化完后 再设定默认值
99 | setTimeout(function(){
100 | //设定默认值
101 | self.setSelectedValue(self.options.defaultVal);
102 | },100)
103 | },
104 |
105 | //设置默认选中值
106 | setSelectedValue: function(value) {
107 |
108 | if(!value)return false;
109 |
110 | var self = this;
111 | var pickers = self.panel.querySelectorAll('.pop-picker');
112 | pickers = Array.prototype.slice.call(pickers);
113 | set(pickers,value)
114 |
115 | //设置
116 | function set(pickers,value){
117 | if(value.length){
118 | var val = value.shift()
119 | var pickerObj = pickers.shift()
120 | pickerObj.picker.setSelectedValue(val,0,function(pickers,value){
121 | setTimeout(function(){
122 | set(pickers,value);
123 | },200)
124 | }.bind(this,pickers,value))
125 | }
126 | }
127 | },
128 |
129 | //填充数据
130 | setData: function(data) {
131 | var self = this;
132 | data = data || [];
133 | self.pickers[0].setItems(data);
134 | },
135 | //获取选中的项(数组)
136 | getSelectedItems: function() {
137 | var self = this;
138 | var items = [];
139 | for (var i in self.pickers) {
140 | var picker = self.pickers[i];
141 | items.push(picker.getSelectedItem() || {});
142 | }
143 | return items;
144 | },
145 | //显示
146 | show: function(callback) {
147 | var self = this;
148 | self.callback = callback;
149 | self.mask.show();
150 | document.body.classList.add($.className('poppicker-active-for-page'));
151 | self.panel.classList.add($.className('active'));
152 | //处理物理返回键
153 | self.__back = $.back;
154 | $.back = function() {
155 | self.hide();
156 | };
157 | },
158 | //隐藏
159 | hide: function() {
160 | var self = this;
161 | if (self.disposed) return;
162 | self.panel.classList.remove($.className('active'));
163 | self.mask.close();
164 | document.body.classList.remove($.className('poppicker-active-for-page'));
165 | //处理物理返回键
166 | $.back=self.__back;
167 | },
168 | dispose: function() {
169 | var self = this;
170 | self.hide();
171 | setTimeout(function() {
172 | self.panel.parentNode.removeChild(self.panel);
173 | for (var name in self) {
174 | self[name] = null;
175 | delete self[name];
176 | };
177 | self.disposed = true;
178 | }, 300);
179 | }
180 | });
181 |
182 | })(mui, document);
183 |
184 | export default mui.PopPicker
185 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-picker
2 | datapicker and citypicker base on MUI of picker
3 |
4 |
5 |
6 | ### Installation
7 |
8 | Using [npm](https://www.npmjs.com/):
9 |
10 | $ npm install --save react-pickers
11 |
12 |
13 | Then with a module bundler like [webpack](https://webpack.github.io/) that supports either CommonJS or ES2015 modules, use as you would anything else:
14 |
15 |
16 | ```js
17 |
18 | // using an ES6 transpiler, like babel
19 | import { DatePicker, CityPicker } from 'react-pickers'
20 |
21 | // not using an ES6 transpiler
22 | var DatePicker = require('react-pickers').DatePicker
23 | var CityPicker = require('react-pickers').CityPicker
24 |
25 |
26 | ```
27 |
28 | ### What's it look like?
29 |
30 | ```js
31 | import React, { Component } from 'react';
32 | import { render } from 'react-dom';
33 |
34 | import 'react-pickers/lib/css/picker.css'
35 | import { CityPicker, DatePicker } from 'react-picker'
36 |
37 |
38 | import city2 from '../lib/city-data'
39 | import city3 from '../lib/city-data-3'
40 |
41 | class App extends Component{
42 |
43 | state = {
44 | showCityPicker: false,
45 | showCity2Picker:false,
46 | showCity3Picker:false,
47 | showDatePicker:false,
48 | showDatePicker2:false,
49 | singleData : [{
50 | value: 'ywj',
51 | text: '董事长 叶文洁'
52 | }, {
53 | value: 'aaa',
54 | text: '总经理 艾AA'
55 | }, {
56 | value: 'lj',
57 | text: '罗辑'
58 | }, {
59 | value: 'ymt',
60 | text: '云天明'
61 | }, {
62 | value: 'shq',
63 | text: '史强'
64 | }, {
65 | value: 'zhbh',
66 | text: '章北海'
67 | }, {
68 | value: 'zhy',
69 | text: '庄颜'
70 | }, {
71 | value: 'gyf',
72 | text: '关一帆'
73 | }, {
74 | value: 'zhz',
75 | text: '智子'
76 | }, {
77 | value: 'gezh',
78 | text: '歌者'
79 | }],
80 | city2: city2,
81 | city3: city3
82 | }
83 |
84 | showCityPicker(){
85 | this.setState({showCityPicker: true })
86 | }
87 |
88 | showCity2Picker(){
89 | this.setState({showCity2Picker: true })
90 | }
91 |
92 | showCity3Picker(){
93 | this.setState({showCity3Picker: true })
94 | }
95 |
96 | ok(){
97 | this.setState({showCityPicker: false })
98 | }
99 |
100 | cl(){
101 | this.setState({showCityPicker: false })
102 | }
103 |
104 |
105 | ok2(){
106 | this.setState({showCity2Picker: false })
107 | }
108 |
109 | cl2(){
110 | this.setState({showCity2Picker: false })
111 | }
112 |
113 | ok3(){
114 | this.setState({showCity3Picker: false })
115 | }
116 |
117 | cl3(){
118 | this.setState({showCity3Picker: false })
119 | }
120 |
121 | ok4(){
122 | this.setState({showDatePicker: false })
123 | }
124 |
125 | cl4(){
126 | this.setState({showDatePicker: false })
127 | }
128 |
129 | ok5(){
130 | this.setState({showDatePicker2: false })
131 | }
132 |
133 | cl5(){
134 | this.setState({showDatePicker2: false })
135 | }
136 |
137 | getData(ret){
138 | console.log(ret);
139 | }
140 |
141 | getData2(ret){
142 | console.log("你选择的城市是:" + ret[0].text + " " + ret[1].text);
143 | }
144 |
145 | getData3(ret){
146 | console.log("你选择的城市是:" + (ret[0] || {}).text + " " + (ret[1] || {}).text + " " + (ret[2] || {}).text);
147 | }
148 |
149 | getData4(ret){
150 | console.log('选择结果: ' + ret);
151 | }
152 |
153 | getData5(ret){
154 | console.log('选择结果: ' + ret);
155 | }
156 |
157 | selectDate(){
158 | this.setState({showDatePicker: true })
159 | }
160 |
161 | selectDate2(){
162 | this.setState({showDatePicker2: true })
163 | }
164 |
165 | render(){
166 | return (
167 |
168 |
普通示例
169 |
170 |
171 |
级联示例
172 |
173 |
174 |
175 |
176 |
177 |
178 |
常规示例
179 |
180 |
181 | 设定年份区间
182 |
183 |
184 |
185 |
186 | )
187 | }
188 | }
189 |
190 |
191 | render(
192 | ,
193 | document.querySelector('#root')
194 | )
195 |
196 | ```
197 |
198 | See more in the [mui-picker](http://dev.dcloud.net.cn/mui/ui/#picker)
199 |
200 |
201 | ### example
202 |
203 | ```js
204 |
205 | npm install
206 |
207 | cd example
208 |
209 | node server.js
210 |
211 | ```
212 |
--------------------------------------------------------------------------------
/lib/css/picker.css:
--------------------------------------------------------------------------------
1 | /*main*/
2 |
3 | .mui-dtpicker h5, .mui-h5 {
4 | font-size: 14px;
5 | font-weight: normal;
6 | color: #8f8f94;
7 | }
8 |
9 | .mui-btn
10 | {
11 | font-size: 14px;
12 | font-weight: 400;
13 | line-height: 1.42;
14 |
15 | position: relative;
16 |
17 | display: inline-block;
18 |
19 | margin-bottom: 0;
20 | padding: 6px 12px;
21 |
22 | cursor: pointer;
23 | -webkit-transition: all;
24 | transition: all;
25 | -webkit-transition-timing-function: linear;
26 | transition-timing-function: linear;
27 | -webkit-transition-duration: .2s;
28 | transition-duration: .2s;
29 | text-align: center;
30 | vertical-align: top;
31 | white-space: nowrap;
32 |
33 | color: #333;
34 | border: 1px solid #ccc;
35 | border-radius: 3px;
36 | border-top-left-radius: 3px;
37 | border-top-right-radius: 3px;
38 | border-bottom-right-radius: 3px;
39 | border-bottom-left-radius: 3px;
40 | background-color: #fff;
41 | background-clip: padding-box;
42 | }
43 |
44 | .mui-btn-primary, .mui-btn-blue
45 | {
46 | color: #fff;
47 | border: 1px solid #007aff;
48 | background-color: #007aff;
49 | }
50 |
51 | .mui-backdrop {
52 | position: fixed;
53 | z-index: 998;
54 | top: 0;
55 | right: 0;
56 | bottom: 0;
57 | left: 0;
58 | background-color: rgba(0, 0, 0, .3);
59 | }
60 |
61 | /**
62 | * 选择列表插件
63 | * varstion 2.0.0
64 | * by Houfeng
65 | * Houfeng@DCloud.io
66 | */
67 |
68 | .mui-picker {
69 | background-color: #ddd;
70 | position: relative;
71 | height: 200px;
72 | overflow: hidden;
73 | border: solid 1px rgba(0, 0, 0, 0.1);
74 | -webkit-user-select: none;
75 | user-select: none;
76 | box-sizing: border-box;
77 | }
78 | .mui-picker-inner {
79 | box-sizing: border-box;
80 | position: relative;
81 | width: 100%;
82 | height: 100%;
83 | overflow: hidden;
84 | -webkit-mask-box-image: -webkit-linear-gradient(bottom, transparent, transparent 5%, #fff 20%, #fff 80%, transparent 95%, transparent);
85 | -webkit-mask-box-image: linear-gradient(top, transparent, transparent 5%, #fff 20%, #fff 80%, transparent 95%, transparent);
86 | }
87 | .mui-pciker-list,
88 | .mui-pciker-rule {
89 | box-sizing: border-box;
90 | padding: 0px;
91 | margin: 0px;
92 | width: 100%;
93 | height: 36px;
94 | line-height: 36px;
95 | position: absolute;
96 | left: 0px;
97 | top: 50%;
98 | margin-top: -18px;
99 | }
100 | .mui-pciker-rule-bg {
101 | z-index: 0;
102 | /*background-color: #cfd5da;*/
103 | }
104 | .mui-pciker-rule-ft {
105 | z-index: 2;
106 | border-top: solid 1px rgba(0, 0, 0, 0.1);
107 | border-bottom: solid 1px rgba(0, 0, 0, 0.1);
108 | /*-webkit-box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.1);*/
109 | /*box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.1);*/
110 | }
111 | .mui-pciker-list {
112 | z-index: 1;
113 | -webkit-transform-style: preserve-3d;
114 | transform-style: preserve-3d;
115 | -webkit-transform: perspective(1000px) rotateY(0deg) rotateX(0deg);
116 | transform: perspective(1000px) rotateY(0deg) rotateX(0deg);
117 | }
118 | .mui-pciker-list li {
119 | width: 100%;
120 | height: 100%;
121 | position: absolute;
122 | text-align: center;
123 | vertical-align: middle;
124 | -webkit-backface-visibility: hidden;
125 | backface-visibility: hidden;
126 | overflow: hidden;
127 | box-sizing: border-box;
128 | font-size: 16px;
129 | font-family: "Helvetica Neue", "Helvetica", "Arial", "sans-serif";
130 | color: #888;
131 | padding: 0px 8px;
132 | white-space: nowrap;
133 | -webkit-text-overflow: ellipsis;
134 | text-overflow: ellipsis;
135 | overflow: hidden;
136 | cursor: default;
137 | visibility: hidden;
138 | }
139 | .mui-pciker-list li.highlight,
140 | .mui-pciker-list li.visible {
141 | visibility: visible;
142 | }
143 | .mui-pciker-list li.highlight {
144 | color: #222;
145 | }
146 | .mui-poppicker {
147 | position: fixed;
148 | left: 0px;
149 | width: 100%;
150 | z-index: 999;
151 | background-color: #eee;
152 | border-top: solid 1px #ccc;
153 | box-shadow: 0px -5px 7px 0px rgba(0, 0, 0, 0.1);
154 | -webkit-transition: .3s;
155 | bottom: 0px;
156 | -webkit-transform: translateY(300px);
157 | }
158 | .mui-poppicker.mui-active {
159 | -webkit-transform: translateY(0px);
160 | }
161 | .mui-android-5-1 .mui-poppicker {
162 | bottom: -300px;
163 | -webkit-transition-property: bottom;
164 | -webkit-transform: none;
165 | }
166 | .mui-android-5-1 .mui-poppicker.mui-active {
167 | bottom: 0px;
168 | -webkit-transition-property: bottom;
169 | -webkit-transform: none;
170 | }
171 | .mui-poppicker-header {
172 | padding: 6px;
173 | font-size: 14px;
174 | color: #888;
175 | }
176 | .mui-poppicker-header .mui-btn {
177 | font-size: 12px;
178 | padding: 5px 10px;
179 | }
180 | .mui-poppicker-btn-cancel {
181 | float: left;
182 | }
183 | .mui-poppicker-btn-ok {
184 | float: right;
185 | }
186 | .mui-poppicker-clear {
187 | clear: both;
188 | height: 0px;
189 | line-height: 0px;
190 | font-size: 0px;
191 | overflow: hidden;
192 | }
193 | .mui-poppicker-body {
194 | position: relative;
195 | width: 100%;
196 | height: 200px;
197 | border-top: solid 1px #ddd;
198 | /*-webkit-perspective: 1200px;
199 | perspective: 1200px;
200 | -webkit-transform-style: preserve-3d;
201 | transform-style: preserve-3d;*/
202 | }
203 | .mui-poppicker-body .mui-picker {
204 | width: 100%;
205 | height: 100%;
206 | margin: 0px;
207 | border: none;
208 | float: left;
209 | }
210 | .mui-dtpicker {
211 | position: fixed;
212 | left: 0px;
213 | width: 100%;
214 | z-index: 999999;
215 | background-color: #eee;
216 | border-top: solid 1px #ccc;
217 | box-shadow: 0px -5px 7px 0px rgba(0, 0, 0, 0.1);
218 | -webkit-transition: .3s;
219 | bottom: 0px;
220 | -webkit-transform: translateY(300px);
221 | }
222 | .mui-dtpicker.mui-active {
223 | -webkit-transform: translateY(0px);
224 | }
225 | /*用于将 html body 禁止滚动条*/
226 |
227 | .mui-dtpicker-active-for-page {
228 | overflow: hidden !important;
229 | }
230 | .mui-android-5-1 .mui-dtpicker {
231 | bottom: -300px;
232 | -webkit-transition-property: bottom;
233 | -webkit-transform: none;
234 | }
235 | .mui-android-5-1 .mui-dtpicker.mui-active {
236 | bottom: 0px;
237 | -webkit-transition-property: bottom;
238 | -webkit-transform: none;
239 | }
240 | .mui-dtpicker-header {
241 | padding: 6px;
242 | font-size: 14px;
243 | color: #888;
244 | }
245 | .mui-dtpicker-header button {
246 | font-size: 12px;
247 | padding: 5px 10px;
248 | }
249 | .mui-dtpicker-header button:last-child {
250 | float: right;
251 | }
252 | .mui-dtpicker-body {
253 | position: relative;
254 | width: 100%;
255 | height: 200px;
256 | /*border-top: solid 1px #eee;
257 | background-color: #fff;*/
258 | }
259 | .mui-ios .mui-dtpicker-body {
260 | -webkit-perspective: 1200px;
261 | perspective: 1200px;
262 | -webkit-transform-style: preserve-3d;
263 | transform-style: preserve-3d;
264 | }
265 | .mui-dtpicker-title h5 {
266 | display: inline-block;
267 | width: 20%;
268 | margin: 0px;
269 | padding: 8px;
270 | text-align: center;
271 | border-top: solid 1px #ddd;
272 | background-color: #f0f0f0;
273 | border-bottom: solid 1px #ccc;
274 | }
275 | .mui-dtpicker .mui-picker {
276 | width: 20%;
277 | height: 100%;
278 | margin: 0px;
279 | float: left;
280 | border: none;
281 | }
282 | /*年月日时分*/
283 |
284 | [data-type="datetime"] .mui-picker,
285 | [data-type="time"] .mui-dtpicker-title h5 {
286 | width: 20%;
287 | }
288 | [data-type="datetime"] [data-id="picker-h"],
289 | [data-type="datetime"] [data-id="title-h"] {
290 | border-left: dotted 1px #ccc;
291 | }
292 | /*年月日*/
293 |
294 | [data-type="date"] .mui-picker,
295 | [data-type="date"] .mui-dtpicker-title h5 {
296 | width: 33.3%;
297 | }
298 | [data-type="date"] [data-id="picker-h"],
299 | [data-type="date"] [data-id="picker-i"],
300 | [data-type="date"] [data-id="title-h"],
301 | [data-type="date"] [data-id="title-i"] {
302 | display: none;
303 | }
304 | /*年月日时*/
305 |
306 | [data-type="hour"] .mui-picker,
307 | [data-type="hour"] .mui-dtpicker-title h5 {
308 | width: 25%;
309 | }
310 | [data-type="hour"] [data-id="picker-i"],
311 | [data-type="hour"] [data-id="title-i"] {
312 | display: none;
313 | }
314 | [data-type="hour"] [data-id="picker-h"],
315 | [data-type="hour"] [data-id="title-h"] {
316 | border-left: dotted 1px #ccc;
317 | }
318 | /*时分*/
319 |
320 | [data-type="time"] .mui-picker,
321 | [data-type="time"] .mui-dtpicker-title h5 {
322 | width: 50%;
323 | }
324 | [data-type="time"] [data-id="picker-y"],
325 | [data-type="time"] [data-id="picker-m"],
326 | [data-type="time"] [data-id="picker-d"],
327 | [data-type="time"] [data-id="title-y"],
328 | [data-type="time"] [data-id="title-m"],
329 | [data-type="time"] [data-id="title-d"] {
330 | display: none;
331 | }
332 | /*年月*/
333 |
334 | [data-type="month"] .mui-picker,
335 | [data-type="month"] .mui-dtpicker-title h5 {
336 | width: 50%;
337 | }
338 | [data-type="month"] [data-id="picker-d"],
339 | [data-type="month"] [data-id="picker-h"],
340 | [data-type="month"] [data-id="picker-i"],
341 | [data-type="month"] [data-id="title-d"],
342 | [data-type="month"] [data-id="title-h"],
343 | [data-type="month"] [data-id="title-i"] {
344 | display: none;
345 | }
346 |
--------------------------------------------------------------------------------
/src/css/picker.css:
--------------------------------------------------------------------------------
1 | /*main*/
2 |
3 | .mui-dtpicker h5, .mui-h5 {
4 | font-size: 14px;
5 | font-weight: normal;
6 | color: #8f8f94;
7 | }
8 |
9 | .mui-btn
10 | {
11 | font-size: 14px;
12 | font-weight: 400;
13 | line-height: 1.42;
14 |
15 | position: relative;
16 |
17 | display: inline-block;
18 |
19 | margin-bottom: 0;
20 | padding: 6px 12px;
21 |
22 | cursor: pointer;
23 | -webkit-transition: all;
24 | transition: all;
25 | -webkit-transition-timing-function: linear;
26 | transition-timing-function: linear;
27 | -webkit-transition-duration: .2s;
28 | transition-duration: .2s;
29 | text-align: center;
30 | vertical-align: top;
31 | white-space: nowrap;
32 |
33 | color: #333;
34 | border: 1px solid #ccc;
35 | border-radius: 3px;
36 | border-top-left-radius: 3px;
37 | border-top-right-radius: 3px;
38 | border-bottom-right-radius: 3px;
39 | border-bottom-left-radius: 3px;
40 | background-color: #fff;
41 | background-clip: padding-box;
42 | }
43 |
44 | .mui-btn-primary, .mui-btn-blue
45 | {
46 | color: #fff;
47 | border: 1px solid #007aff;
48 | background-color: #007aff;
49 | }
50 |
51 | .mui-backdrop {
52 | position: fixed;
53 | z-index: 998;
54 | top: 0;
55 | right: 0;
56 | bottom: 0;
57 | left: 0;
58 | background-color: rgba(0, 0, 0, .3);
59 | }
60 |
61 | /**
62 | * 选择列表插件
63 | * varstion 2.0.0
64 | * by Houfeng
65 | * Houfeng@DCloud.io
66 | */
67 |
68 | .mui-picker {
69 | background-color: #ddd;
70 | position: relative;
71 | height: 200px;
72 | overflow: hidden;
73 | border: solid 1px rgba(0, 0, 0, 0.1);
74 | -webkit-user-select: none;
75 | user-select: none;
76 | box-sizing: border-box;
77 | }
78 | .mui-picker-inner {
79 | box-sizing: border-box;
80 | position: relative;
81 | width: 100%;
82 | height: 100%;
83 | overflow: hidden;
84 | -webkit-mask-box-image: -webkit-linear-gradient(bottom, transparent, transparent 5%, #fff 20%, #fff 80%, transparent 95%, transparent);
85 | -webkit-mask-box-image: linear-gradient(top, transparent, transparent 5%, #fff 20%, #fff 80%, transparent 95%, transparent);
86 | }
87 | .mui-pciker-list,
88 | .mui-pciker-rule {
89 | box-sizing: border-box;
90 | padding: 0px;
91 | margin: 0px;
92 | width: 100%;
93 | height: 36px;
94 | line-height: 36px;
95 | position: absolute;
96 | left: 0px;
97 | top: 50%;
98 | margin-top: -18px;
99 | }
100 | .mui-pciker-rule-bg {
101 | z-index: 0;
102 | /*background-color: #cfd5da;*/
103 | }
104 | .mui-pciker-rule-ft {
105 | z-index: 2;
106 | border-top: solid 1px rgba(0, 0, 0, 0.1);
107 | border-bottom: solid 1px rgba(0, 0, 0, 0.1);
108 | /*-webkit-box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.1);*/
109 | /*box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.1);*/
110 | }
111 | .mui-pciker-list {
112 | z-index: 1;
113 | -webkit-transform-style: preserve-3d;
114 | transform-style: preserve-3d;
115 | -webkit-transform: perspective(1000px) rotateY(0deg) rotateX(0deg);
116 | transform: perspective(1000px) rotateY(0deg) rotateX(0deg);
117 | }
118 | .mui-pciker-list li {
119 | width: 100%;
120 | height: 100%;
121 | position: absolute;
122 | text-align: center;
123 | vertical-align: middle;
124 | -webkit-backface-visibility: hidden;
125 | backface-visibility: hidden;
126 | overflow: hidden;
127 | box-sizing: border-box;
128 | font-size: 16px;
129 | font-family: "Helvetica Neue", "Helvetica", "Arial", "sans-serif";
130 | color: #888;
131 | padding: 0px 8px;
132 | white-space: nowrap;
133 | -webkit-text-overflow: ellipsis;
134 | text-overflow: ellipsis;
135 | overflow: hidden;
136 | cursor: default;
137 | visibility: hidden;
138 | }
139 | .mui-pciker-list li.highlight,
140 | .mui-pciker-list li.visible {
141 | visibility: visible;
142 | }
143 | .mui-pciker-list li.highlight {
144 | color: #222;
145 | }
146 | .mui-poppicker {
147 | position: fixed;
148 | left: 0px;
149 | width: 100%;
150 | z-index: 999;
151 | background-color: #eee;
152 | border-top: solid 1px #ccc;
153 | box-shadow: 0px -5px 7px 0px rgba(0, 0, 0, 0.1);
154 | -webkit-transition: .3s;
155 | bottom: 0px;
156 | -webkit-transform: translateY(300px);
157 | }
158 | .mui-poppicker.mui-active {
159 | -webkit-transform: translateY(0px);
160 | }
161 | .mui-android-5-1 .mui-poppicker {
162 | bottom: -300px;
163 | -webkit-transition-property: bottom;
164 | -webkit-transform: none;
165 | }
166 | .mui-android-5-1 .mui-poppicker.mui-active {
167 | bottom: 0px;
168 | -webkit-transition-property: bottom;
169 | -webkit-transform: none;
170 | }
171 | .mui-poppicker-header {
172 | padding: 6px;
173 | font-size: 14px;
174 | color: #888;
175 | }
176 | .mui-poppicker-header .mui-btn {
177 | font-size: 12px;
178 | padding: 5px 10px;
179 | }
180 | .mui-poppicker-btn-cancel {
181 | float: left;
182 | }
183 | .mui-poppicker-btn-ok {
184 | float: right;
185 | }
186 | .mui-poppicker-clear {
187 | clear: both;
188 | height: 0px;
189 | line-height: 0px;
190 | font-size: 0px;
191 | overflow: hidden;
192 | }
193 | .mui-poppicker-body {
194 | position: relative;
195 | width: 100%;
196 | height: 200px;
197 | border-top: solid 1px #ddd;
198 | /*-webkit-perspective: 1200px;
199 | perspective: 1200px;
200 | -webkit-transform-style: preserve-3d;
201 | transform-style: preserve-3d;*/
202 | }
203 | .mui-poppicker-body .mui-picker {
204 | width: 100%;
205 | height: 100%;
206 | margin: 0px;
207 | border: none;
208 | float: left;
209 | }
210 | .mui-dtpicker {
211 | position: fixed;
212 | left: 0px;
213 | width: 100%;
214 | z-index: 999999;
215 | background-color: #eee;
216 | border-top: solid 1px #ccc;
217 | box-shadow: 0px -5px 7px 0px rgba(0, 0, 0, 0.1);
218 | -webkit-transition: .3s;
219 | bottom: 0px;
220 | -webkit-transform: translateY(300px);
221 | }
222 | .mui-dtpicker.mui-active {
223 | -webkit-transform: translateY(0px);
224 | }
225 | /*用于将 html body 禁止滚动条*/
226 |
227 | .mui-dtpicker-active-for-page {
228 | overflow: hidden !important;
229 | }
230 | .mui-android-5-1 .mui-dtpicker {
231 | bottom: -300px;
232 | -webkit-transition-property: bottom;
233 | -webkit-transform: none;
234 | }
235 | .mui-android-5-1 .mui-dtpicker.mui-active {
236 | bottom: 0px;
237 | -webkit-transition-property: bottom;
238 | -webkit-transform: none;
239 | }
240 | .mui-dtpicker-header {
241 | padding: 6px;
242 | font-size: 14px;
243 | color: #888;
244 | }
245 | .mui-dtpicker-header button {
246 | font-size: 12px;
247 | padding: 5px 10px;
248 | }
249 | .mui-dtpicker-header button:last-child {
250 | float: right;
251 | }
252 | .mui-dtpicker-body {
253 | position: relative;
254 | width: 100%;
255 | height: 200px;
256 | /*border-top: solid 1px #eee;
257 | background-color: #fff;*/
258 | }
259 | .mui-ios .mui-dtpicker-body {
260 | -webkit-perspective: 1200px;
261 | perspective: 1200px;
262 | -webkit-transform-style: preserve-3d;
263 | transform-style: preserve-3d;
264 | }
265 | .mui-dtpicker-title h5 {
266 | display: inline-block;
267 | width: 20%;
268 | margin: 0px;
269 | padding: 8px;
270 | text-align: center;
271 | border-top: solid 1px #ddd;
272 | background-color: #f0f0f0;
273 | border-bottom: solid 1px #ccc;
274 | }
275 | .mui-dtpicker .mui-picker {
276 | width: 20%;
277 | height: 100%;
278 | margin: 0px;
279 | float: left;
280 | border: none;
281 | }
282 | /*年月日时分*/
283 |
284 | [data-type="datetime"] .mui-picker,
285 | [data-type="time"] .mui-dtpicker-title h5 {
286 | width: 20%;
287 | }
288 | [data-type="datetime"] [data-id="picker-h"],
289 | [data-type="datetime"] [data-id="title-h"] {
290 | border-left: dotted 1px #ccc;
291 | }
292 | /*年月日*/
293 |
294 | [data-type="date"] .mui-picker,
295 | [data-type="date"] .mui-dtpicker-title h5 {
296 | width: 33.3%;
297 | }
298 | [data-type="date"] [data-id="picker-h"],
299 | [data-type="date"] [data-id="picker-i"],
300 | [data-type="date"] [data-id="title-h"],
301 | [data-type="date"] [data-id="title-i"] {
302 | display: none;
303 | }
304 | /*年月日时*/
305 |
306 | [data-type="hour"] .mui-picker,
307 | [data-type="hour"] .mui-dtpicker-title h5 {
308 | width: 25%;
309 | }
310 | [data-type="hour"] [data-id="picker-i"],
311 | [data-type="hour"] [data-id="title-i"] {
312 | display: none;
313 | }
314 | [data-type="hour"] [data-id="picker-h"],
315 | [data-type="hour"] [data-id="title-h"] {
316 | border-left: dotted 1px #ccc;
317 | }
318 | /*时分*/
319 |
320 | [data-type="time"] .mui-picker,
321 | [data-type="time"] .mui-dtpicker-title h5 {
322 | width: 50%;
323 | }
324 | [data-type="time"] [data-id="picker-y"],
325 | [data-type="time"] [data-id="picker-m"],
326 | [data-type="time"] [data-id="picker-d"],
327 | [data-type="time"] [data-id="title-y"],
328 | [data-type="time"] [data-id="title-m"],
329 | [data-type="time"] [data-id="title-d"] {
330 | display: none;
331 | }
332 | /*年月*/
333 |
334 | [data-type="month"] .mui-picker,
335 | [data-type="month"] .mui-dtpicker-title h5 {
336 | width: 50%;
337 | }
338 | [data-type="month"] [data-id="picker-d"],
339 | [data-type="month"] [data-id="picker-h"],
340 | [data-type="month"] [data-id="picker-i"],
341 | [data-type="month"] [data-id="title-d"],
342 | [data-type="month"] [data-id="title-h"],
343 | [data-type="month"] [data-id="title-i"] {
344 | display: none;
345 | }
346 |
--------------------------------------------------------------------------------
/src/js/picker.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 选择列表插件
3 | * varstion 2.0.0
4 | * by Houfeng
5 | * Houfeng@DCloud.io
6 | */
7 |
8 | import mui from './mui'
9 |
10 | (function($, window, document, undefined) {
11 |
12 | var MAX_EXCEED = 30;
13 | var VISIBLE_RANGE = 90;
14 | var DEFAULT_ITEM_HEIGHT = 40;
15 | var BLUR_WIDTH = 10;
16 |
17 | var rad2deg = $.rad2deg = function(rad) {
18 | return rad / (Math.PI / 180);
19 | };
20 |
21 | var deg2rad = $.deg2rad = function(deg) {
22 | return deg * (Math.PI / 180);
23 | };
24 |
25 | var platform = navigator.platform.toLowerCase();
26 | var userAgent = navigator.userAgent.toLowerCase();
27 | var isIos = (userAgent.indexOf('iphone') > -1 ||
28 | userAgent.indexOf('ipad') > -1 ||
29 | userAgent.indexOf('ipod') > -1) &&
30 | (platform.indexOf('iphone') > -1 ||
31 | platform.indexOf('ipad') > -1 ||
32 | platform.indexOf('ipod') > -1);
33 | //alert(isIos);
34 |
35 | var Picker = $.Picker = function(holder, options) {
36 | var self = this;
37 | self.holder = holder;
38 | self.options = options || {};
39 | self.init();
40 | self.initInertiaParams();
41 | self.calcElementItemPostion(true);
42 | self.bindEvent();
43 | };
44 |
45 | Picker.prototype.findElementItems = function() {
46 | var self = this;
47 | self.elementItems = [].slice.call(self.holder.querySelectorAll('li'));
48 | return self.elementItems;
49 | };
50 |
51 | Picker.prototype.init = function() {
52 | var self = this;
53 | self.list = self.holder.querySelector('ul');
54 | self.findElementItems();
55 | self.standardHeight = document.querySelector('.mui-pciker-rule').getBoundingClientRect()
56 | self.height = self.holder.offsetHeight;
57 | self.r = self.height / 2 - BLUR_WIDTH;
58 | self.d = self.r * 2;
59 | self.itemHeight = typeof self.standardHeight == 'object' ? self.standardHeight.height : DEFAULT_ITEM_HEIGHT;
60 | self.itemAngle = parseInt(self.calcAngle(self.itemHeight * 0.8));
61 | self.hightlightRange = self.itemAngle / 2;
62 | self.visibleRange = VISIBLE_RANGE;
63 | self.beginAngle = 0;
64 | self.beginExceed = self.beginAngle - MAX_EXCEED;
65 | self.list.angle = self.beginAngle;
66 | if (isIos) {
67 | self.list.style.webkitTransformOrigin = "center center " + self.r + "px";
68 | }
69 | };
70 |
71 | Picker.prototype.calcElementItemPostion = function(andGenerateItms) {
72 | var self = this;
73 | if (andGenerateItms) {
74 | self.items = [];
75 | }
76 | self.elementItems.forEach(function(item) {
77 | var index = self.elementItems.indexOf(item);
78 | self.endAngle = self.itemAngle * index;
79 | item.angle = self.endAngle;
80 | item.style.webkitTransformOrigin = "center center -" + self.r + "px";
81 | item.style.webkitTransform = "translateZ(" + self.r + "px) rotateX(" + (-self.endAngle) + "deg)";
82 | if (andGenerateItms) {
83 | var dataItem = {};
84 | dataItem.text = item.innerHTML || '';
85 | dataItem.value = item.getAttribute('data-value') || dataItem.text;
86 | self.items.push(dataItem);
87 | }
88 | });
89 | self.endExceed = self.endAngle + MAX_EXCEED;
90 | self.calcElementItemVisibility(self.beginAngle);
91 | };
92 |
93 | Picker.prototype.calcAngle = function(c) {
94 | var self = this;
95 | var a = parseFloat(self.r);
96 | var b = parseFloat(self.r);
97 | //直径的整倍数部分直接乘以 180
98 | c = Math.abs(c); //只算角度不关心正否值
99 | var intDeg = parseInt(c / self.d) * 180;
100 | c = c % self.d;
101 | //余弦
102 | var cosC = (a * a + b * b - c * c) / (2 * a * b);
103 | var angleC = intDeg + rad2deg(Math.acos(cosC));
104 | return angleC;
105 | };
106 |
107 | Picker.prototype.calcElementItemVisibility = function(angle) {
108 | var self = this;
109 | self.elementItems.forEach(function(item) {
110 | var difference = Math.abs(item.angle - angle);
111 | if (difference < self.hightlightRange) {
112 | item.classList.add('highlight');
113 | } else if (difference < self.visibleRange) {
114 | item.classList.add('visible');
115 | item.classList.remove('highlight');
116 | } else {
117 | item.classList.remove('highlight');
118 | item.classList.remove('visible');
119 | }
120 | });
121 | };
122 |
123 | Picker.prototype.setAngle = function(angle) {
124 | var self = this;
125 | self.list.angle = angle;
126 | self.list.style.webkitTransform = "perspective(1000px) rotateY(0deg) rotateX(" + angle + "deg)";
127 | self.calcElementItemVisibility(angle);
128 | };
129 |
130 | Picker.prototype.bindEvent = function() {
131 | var self = this;
132 | var lastAngle = 0;
133 | var startY = null;
134 | var isPicking = false;
135 | self.holder.addEventListener($.EVENT_START, function(event) {
136 | isPicking = true;
137 | event.preventDefault();
138 | self.list.style.webkitTransition = '';
139 | startY = (event.changedTouches ? event.changedTouches[0] : event).pageY;
140 | lastAngle = self.list.angle;
141 | self.updateInertiaParams(event, true);
142 | }, false);
143 | self.holder.addEventListener($.EVENT_END, function(event) {
144 | isPicking = false;
145 | event.preventDefault();
146 | self.startInertiaScroll(event);
147 | }, false);
148 | self.holder.addEventListener($.EVENT_CANCEL, function(event) {
149 | isPicking = false;
150 | event.preventDefault();
151 | self.startInertiaScroll(event);
152 | }, false);
153 | self.holder.addEventListener($.EVENT_MOVE, function(event) {
154 | if (!isPicking) {
155 | return;
156 | }
157 | event.preventDefault();
158 | var endY = (event.changedTouches ? event.changedTouches[0] : event).pageY;
159 | var dragRange = endY - startY;
160 | var dragAngle = self.calcAngle(dragRange);
161 | var newAngle = dragRange > 0 ? lastAngle - dragAngle : lastAngle + dragAngle;
162 | if (newAngle > self.endExceed) {
163 | newAngle = self.endExceed
164 | }
165 | if (newAngle < self.beginExceed) {
166 | newAngle = self.beginExceed
167 | }
168 | self.setAngle(newAngle);
169 | self.updateInertiaParams(event);
170 | }, false);
171 | //--
172 | self.list.addEventListener('tap', function(event) {
173 | elementItem = event.target;
174 | if (elementItem.tagName == 'LI') {
175 | self.setSelectedIndex(self.elementItems.indexOf(elementItem), 200);
176 | }
177 | }, false);
178 | };
179 |
180 | Picker.prototype.initInertiaParams = function() {
181 | var self = this;
182 | self.lastMoveTime = 0;
183 | self.lastMoveStart = 0;
184 | self.stopInertiaMove = false;
185 | };
186 |
187 | Picker.prototype.updateInertiaParams = function(event, isStart) {
188 | var self = this;
189 | var point = event.changedTouches ? event.changedTouches[0] : event;
190 | if (isStart) {
191 | self.lastMoveStart = point.pageY;
192 | self.lastMoveTime = event.timeStamp || Date.now();
193 | self.startAngle = self.list.angle;
194 | } else {
195 | var nowTime = event.timeStamp || Date.now();
196 | if (nowTime - self.lastMoveTime > 300) {
197 | self.lastMoveTime = nowTime;
198 | self.lastMoveStart = point.pageY;
199 | }
200 | }
201 | self.stopInertiaMove = true;
202 | };
203 |
204 | Picker.prototype.startInertiaScroll = function(event) {
205 | var self = this;
206 | var point = event.changedTouches ? event.changedTouches[0] : event;
207 | /**
208 | * 缓动代码
209 | */
210 | var nowTime = event.timeStamp || Date.now();
211 | var v = (point.pageY - self.lastMoveStart) / (nowTime - self.lastMoveTime); //最后一段时间手指划动速度
212 | var dir = v > 0 ? -1 : 1; //加速度方向
213 | var deceleration = dir * 0.0006 * -1;
214 | var duration = Math.abs(v / deceleration); // 速度消减至0所需时间
215 | var dist = v * duration / 2; //最终移动多少
216 | var startAngle = self.list.angle;
217 | var distAngle = self.calcAngle(dist) * dir;
218 | //----
219 | var srcDistAngle = distAngle;
220 | if (startAngle + distAngle < self.beginExceed) {
221 | distAngle = self.beginExceed - startAngle;
222 | duration = duration * (distAngle / srcDistAngle) * 0.6;
223 | }
224 | if (startAngle + distAngle > self.endExceed) {
225 | distAngle = self.endExceed - startAngle;
226 | duration = duration * (distAngle / srcDistAngle) * 0.6;
227 | }
228 | //----
229 | if (distAngle == 0) {
230 | self.endScroll();
231 | return;
232 | }
233 | self.scrollDistAngle(nowTime, startAngle, distAngle, duration);
234 | };
235 |
236 | Picker.prototype.scrollDistAngle = function(nowTime, startAngle, distAngle, duration) {
237 | var self = this;
238 | self.stopInertiaMove = false;
239 | (function(nowTime, startAngle, distAngle, duration) {
240 | var frameInterval = 13;
241 | var stepCount = duration / frameInterval;
242 | var stepIndex = 0;
243 | (function inertiaMove() {
244 | if (self.stopInertiaMove) return;
245 | var newAngle = self.quartEaseOut(stepIndex, startAngle, distAngle, stepCount);
246 | self.setAngle(newAngle);
247 | stepIndex++;
248 | if (stepIndex > stepCount - 1 || newAngle < self.beginExceed || newAngle > self.endExceed) {
249 | self.endScroll();
250 | return;
251 | }
252 | setTimeout(inertiaMove, frameInterval);
253 | })();
254 | })(nowTime, startAngle, distAngle, duration);
255 | };
256 |
257 | Picker.prototype.quartEaseOut = function(t, b, c, d) {
258 | return -c * ((t = t / d - 1) * t * t * t - 1) + b;
259 | };
260 |
261 | Picker.prototype.endScroll = function() {
262 | var self = this;
263 | if (self.list.angle < self.beginAngle) {
264 | self.list.style.webkitTransition = "150ms ease-out";
265 | self.setAngle(self.beginAngle);
266 | } else if (self.list.angle > self.endAngle) {
267 | self.list.style.webkitTransition = "150ms ease-out";
268 | self.setAngle(self.endAngle);
269 | } else {
270 | var index = parseInt((self.list.angle / self.itemAngle).toFixed(0));
271 | self.list.style.webkitTransition = "100ms ease-out";
272 | self.setAngle(self.itemAngle * index);
273 | }
274 | self.triggerChange();
275 | };
276 |
277 | Picker.prototype.triggerChange = function(force) {
278 | var self = this;
279 | setTimeout(function() {
280 | var index = self.getSelectedIndex();
281 | var item = self.items[index];
282 | if ($.trigger && (index != self.lastIndex || force === true)) {
283 | $.trigger(self.holder, 'change', {
284 | "index": index,
285 | "item": item
286 | });
287 | //console.log('change:' + index);
288 | }
289 | self.lastIndex = index;
290 | typeof force === 'function' && force();
291 | }, 0);
292 | };
293 |
294 | Picker.prototype.correctAngle = function(angle) {
295 | var self = this;
296 | if (angle < self.beginAngle) {
297 | return self.beginAngle;
298 | } else if (angle > self.endAngle) {
299 | return self.endAngle;
300 | } else {
301 | return angle;
302 | }
303 | };
304 |
305 | Picker.prototype.setItems = function(items) {
306 | var self = this;
307 | self.items = items || [];
308 | var buffer = [];
309 | self.items.forEach(function(item) {
310 | if (item !== null && item !== undefined) {
311 | buffer.push('' + (item.text || item) + '');
312 | }
313 | });
314 | self.list.innerHTML = buffer.join('');
315 | self.findElementItems();
316 | self.calcElementItemPostion();
317 | self.setAngle(self.correctAngle(self.list.angle));
318 | self.triggerChange(true);
319 | };
320 |
321 | Picker.prototype.getItems = function() {
322 | var self = this;
323 | return self.items;
324 | };
325 |
326 | Picker.prototype.getSelectedIndex = function() {
327 | var self = this;
328 | return parseInt((self.list.angle / self.itemAngle).toFixed(0));
329 | };
330 |
331 | Picker.prototype.setSelectedIndex = function(index, duration, callback) {
332 | var self = this;
333 | self.list.style.webkitTransition = '';
334 | var angle = self.correctAngle(self.itemAngle * index);
335 | if (duration && duration > 0) {
336 | var distAngle = angle - self.list.angle;
337 | self.scrollDistAngle(Date.now(), self.list.angle, distAngle, duration);
338 | } else {
339 | self.setAngle(angle);
340 | }
341 | self.triggerChange(callback);
342 | };
343 |
344 | Picker.prototype.getSelectedItem = function() {
345 | var self = this;
346 | return self.items[self.getSelectedIndex()];
347 | };
348 |
349 | Picker.prototype.getSelectedValue = function() {
350 | var self = this;
351 | return (self.items[self.getSelectedIndex()] || {}).value;
352 | };
353 |
354 | Picker.prototype.getSelectedText = function() {
355 | var self = this;
356 | return (self.items[self.getSelectedIndex()] || {}).text;
357 | };
358 |
359 | Picker.prototype.setSelectedValue = function(value, duration, callback) {
360 | var self = this;
361 | for (var index in self.items) {
362 | var item = self.items[index];
363 | if (item.value == value) {
364 | self.setSelectedIndex(index, duration, callback);
365 | return;
366 | }
367 | }
368 | };
369 |
370 | if ($.fn) {
371 | $.fn.picker = function(options) {
372 | //遍历选择的元素
373 | this.each(function(i, element) {
374 | if (element.picker) return;
375 | if (options) {
376 | element.picker = new Picker(element, options);
377 | } else {
378 | var optionsText = element.getAttribute('data-picker-options');
379 | var _options = optionsText ? JSON.parse(optionsText) : {};
380 | element.picker = new Picker(element, _options);
381 | }
382 | });
383 | return this[0] ? this[0].picker : null;
384 | };
385 |
386 | //自动初始化
387 | $.ready(function() {
388 | $('.mui-picker').picker();
389 | });
390 | }
391 |
392 | })(mui || window, window, document, undefined);
393 |
--------------------------------------------------------------------------------
/lib/js/picker.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; /**
4 | * 选择列表插件
5 | * varstion 2.0.0
6 | * by Houfeng
7 | * Houfeng@DCloud.io
8 | */
9 |
10 | var _mui = require('./mui');
11 |
12 | var _mui2 = _interopRequireDefault(_mui);
13 |
14 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15 |
16 | (function ($, window, document, undefined) {
17 |
18 | var MAX_EXCEED = 30;
19 | var VISIBLE_RANGE = 90;
20 | var DEFAULT_ITEM_HEIGHT = 40;
21 | var BLUR_WIDTH = 10;
22 |
23 | var rad2deg = $.rad2deg = function (rad) {
24 | return rad / (Math.PI / 180);
25 | };
26 |
27 | var deg2rad = $.deg2rad = function (deg) {
28 | return deg * (Math.PI / 180);
29 | };
30 |
31 | var platform = navigator.platform.toLowerCase();
32 | var userAgent = navigator.userAgent.toLowerCase();
33 | var isIos = (userAgent.indexOf('iphone') > -1 || userAgent.indexOf('ipad') > -1 || userAgent.indexOf('ipod') > -1) && (platform.indexOf('iphone') > -1 || platform.indexOf('ipad') > -1 || platform.indexOf('ipod') > -1);
34 | //alert(isIos);
35 |
36 | var Picker = $.Picker = function (holder, options) {
37 | var self = this;
38 | self.holder = holder;
39 | self.options = options || {};
40 | self.init();
41 | self.initInertiaParams();
42 | self.calcElementItemPostion(true);
43 | self.bindEvent();
44 | };
45 |
46 | Picker.prototype.findElementItems = function () {
47 | var self = this;
48 | self.elementItems = [].slice.call(self.holder.querySelectorAll('li'));
49 | return self.elementItems;
50 | };
51 |
52 | Picker.prototype.init = function () {
53 | var self = this;
54 | self.list = self.holder.querySelector('ul');
55 | self.findElementItems();
56 | self.standardHeight = document.querySelector('.mui-pciker-rule').getBoundingClientRect();
57 | self.height = self.holder.offsetHeight;
58 | self.r = self.height / 2 - BLUR_WIDTH;
59 | self.d = self.r * 2;
60 | self.itemHeight = _typeof(self.standardHeight) == 'object' ? self.standardHeight.height : DEFAULT_ITEM_HEIGHT;
61 | self.itemAngle = parseInt(self.calcAngle(self.itemHeight * 0.8));
62 | self.hightlightRange = self.itemAngle / 2;
63 | self.visibleRange = VISIBLE_RANGE;
64 | self.beginAngle = 0;
65 | self.beginExceed = self.beginAngle - MAX_EXCEED;
66 | self.list.angle = self.beginAngle;
67 | if (isIos) {
68 | self.list.style.webkitTransformOrigin = "center center " + self.r + "px";
69 | }
70 | };
71 |
72 | Picker.prototype.calcElementItemPostion = function (andGenerateItms) {
73 | var self = this;
74 | if (andGenerateItms) {
75 | self.items = [];
76 | }
77 | self.elementItems.forEach(function (item) {
78 | var index = self.elementItems.indexOf(item);
79 | self.endAngle = self.itemAngle * index;
80 | item.angle = self.endAngle;
81 | item.style.webkitTransformOrigin = "center center -" + self.r + "px";
82 | item.style.webkitTransform = "translateZ(" + self.r + "px) rotateX(" + -self.endAngle + "deg)";
83 | if (andGenerateItms) {
84 | var dataItem = {};
85 | dataItem.text = item.innerHTML || '';
86 | dataItem.value = item.getAttribute('data-value') || dataItem.text;
87 | self.items.push(dataItem);
88 | }
89 | });
90 | self.endExceed = self.endAngle + MAX_EXCEED;
91 | self.calcElementItemVisibility(self.beginAngle);
92 | };
93 |
94 | Picker.prototype.calcAngle = function (c) {
95 | var self = this;
96 | var a = parseFloat(self.r);
97 | var b = parseFloat(self.r);
98 | //直径的整倍数部分直接乘以 180
99 | c = Math.abs(c); //只算角度不关心正否值
100 | var intDeg = parseInt(c / self.d) * 180;
101 | c = c % self.d;
102 | //余弦
103 | var cosC = (a * a + b * b - c * c) / (2 * a * b);
104 | var angleC = intDeg + rad2deg(Math.acos(cosC));
105 | return angleC;
106 | };
107 |
108 | Picker.prototype.calcElementItemVisibility = function (angle) {
109 | var self = this;
110 | self.elementItems.forEach(function (item) {
111 | var difference = Math.abs(item.angle - angle);
112 | if (difference < self.hightlightRange) {
113 | item.classList.add('highlight');
114 | } else if (difference < self.visibleRange) {
115 | item.classList.add('visible');
116 | item.classList.remove('highlight');
117 | } else {
118 | item.classList.remove('highlight');
119 | item.classList.remove('visible');
120 | }
121 | });
122 | };
123 |
124 | Picker.prototype.setAngle = function (angle) {
125 | var self = this;
126 | self.list.angle = angle;
127 | self.list.style.webkitTransform = "perspective(1000px) rotateY(0deg) rotateX(" + angle + "deg)";
128 | self.calcElementItemVisibility(angle);
129 | };
130 |
131 | Picker.prototype.bindEvent = function () {
132 | var self = this;
133 | var lastAngle = 0;
134 | var startY = null;
135 | var isPicking = false;
136 | self.holder.addEventListener($.EVENT_START, function (event) {
137 | isPicking = true;
138 | event.preventDefault();
139 | self.list.style.webkitTransition = '';
140 | startY = (event.changedTouches ? event.changedTouches[0] : event).pageY;
141 | lastAngle = self.list.angle;
142 | self.updateInertiaParams(event, true);
143 | }, false);
144 | self.holder.addEventListener($.EVENT_END, function (event) {
145 | isPicking = false;
146 | event.preventDefault();
147 | self.startInertiaScroll(event);
148 | }, false);
149 | self.holder.addEventListener($.EVENT_CANCEL, function (event) {
150 | isPicking = false;
151 | event.preventDefault();
152 | self.startInertiaScroll(event);
153 | }, false);
154 | self.holder.addEventListener($.EVENT_MOVE, function (event) {
155 | if (!isPicking) {
156 | return;
157 | }
158 | event.preventDefault();
159 | var endY = (event.changedTouches ? event.changedTouches[0] : event).pageY;
160 | var dragRange = endY - startY;
161 | var dragAngle = self.calcAngle(dragRange);
162 | var newAngle = dragRange > 0 ? lastAngle - dragAngle : lastAngle + dragAngle;
163 | if (newAngle > self.endExceed) {
164 | newAngle = self.endExceed;
165 | }
166 | if (newAngle < self.beginExceed) {
167 | newAngle = self.beginExceed;
168 | }
169 | self.setAngle(newAngle);
170 | self.updateInertiaParams(event);
171 | }, false);
172 | //--
173 | self.list.addEventListener('tap', function (event) {
174 | elementItem = event.target;
175 | if (elementItem.tagName == 'LI') {
176 | self.setSelectedIndex(self.elementItems.indexOf(elementItem), 200);
177 | }
178 | }, false);
179 | };
180 |
181 | Picker.prototype.initInertiaParams = function () {
182 | var self = this;
183 | self.lastMoveTime = 0;
184 | self.lastMoveStart = 0;
185 | self.stopInertiaMove = false;
186 | };
187 |
188 | Picker.prototype.updateInertiaParams = function (event, isStart) {
189 | var self = this;
190 | var point = event.changedTouches ? event.changedTouches[0] : event;
191 | if (isStart) {
192 | self.lastMoveStart = point.pageY;
193 | self.lastMoveTime = event.timeStamp || Date.now();
194 | self.startAngle = self.list.angle;
195 | } else {
196 | var nowTime = event.timeStamp || Date.now();
197 | if (nowTime - self.lastMoveTime > 300) {
198 | self.lastMoveTime = nowTime;
199 | self.lastMoveStart = point.pageY;
200 | }
201 | }
202 | self.stopInertiaMove = true;
203 | };
204 |
205 | Picker.prototype.startInertiaScroll = function (event) {
206 | var self = this;
207 | var point = event.changedTouches ? event.changedTouches[0] : event;
208 | /**
209 | * 缓动代码
210 | */
211 | var nowTime = event.timeStamp || Date.now();
212 | var v = (point.pageY - self.lastMoveStart) / (nowTime - self.lastMoveTime); //最后一段时间手指划动速度
213 | var dir = v > 0 ? -1 : 1; //加速度方向
214 | var deceleration = dir * 0.0006 * -1;
215 | var duration = Math.abs(v / deceleration); // 速度消减至0所需时间
216 | var dist = v * duration / 2; //最终移动多少
217 | var startAngle = self.list.angle;
218 | var distAngle = self.calcAngle(dist) * dir;
219 | //----
220 | var srcDistAngle = distAngle;
221 | if (startAngle + distAngle < self.beginExceed) {
222 | distAngle = self.beginExceed - startAngle;
223 | duration = duration * (distAngle / srcDistAngle) * 0.6;
224 | }
225 | if (startAngle + distAngle > self.endExceed) {
226 | distAngle = self.endExceed - startAngle;
227 | duration = duration * (distAngle / srcDistAngle) * 0.6;
228 | }
229 | //----
230 | if (distAngle == 0) {
231 | self.endScroll();
232 | return;
233 | }
234 | self.scrollDistAngle(nowTime, startAngle, distAngle, duration);
235 | };
236 |
237 | Picker.prototype.scrollDistAngle = function (nowTime, startAngle, distAngle, duration) {
238 | var self = this;
239 | self.stopInertiaMove = false;
240 | (function (nowTime, startAngle, distAngle, duration) {
241 | var frameInterval = 13;
242 | var stepCount = duration / frameInterval;
243 | var stepIndex = 0;
244 | (function inertiaMove() {
245 | if (self.stopInertiaMove) return;
246 | var newAngle = self.quartEaseOut(stepIndex, startAngle, distAngle, stepCount);
247 | self.setAngle(newAngle);
248 | stepIndex++;
249 | if (stepIndex > stepCount - 1 || newAngle < self.beginExceed || newAngle > self.endExceed) {
250 | self.endScroll();
251 | return;
252 | }
253 | setTimeout(inertiaMove, frameInterval);
254 | })();
255 | })(nowTime, startAngle, distAngle, duration);
256 | };
257 |
258 | Picker.prototype.quartEaseOut = function (t, b, c, d) {
259 | return -c * ((t = t / d - 1) * t * t * t - 1) + b;
260 | };
261 |
262 | Picker.prototype.endScroll = function () {
263 | var self = this;
264 | if (self.list.angle < self.beginAngle) {
265 | self.list.style.webkitTransition = "150ms ease-out";
266 | self.setAngle(self.beginAngle);
267 | } else if (self.list.angle > self.endAngle) {
268 | self.list.style.webkitTransition = "150ms ease-out";
269 | self.setAngle(self.endAngle);
270 | } else {
271 | var index = parseInt((self.list.angle / self.itemAngle).toFixed(0));
272 | self.list.style.webkitTransition = "100ms ease-out";
273 | self.setAngle(self.itemAngle * index);
274 | }
275 | self.triggerChange();
276 | };
277 |
278 | Picker.prototype.triggerChange = function (force) {
279 | var self = this;
280 | setTimeout(function () {
281 | var index = self.getSelectedIndex();
282 | var item = self.items[index];
283 | if ($.trigger && (index != self.lastIndex || force === true)) {
284 | $.trigger(self.holder, 'change', {
285 | "index": index,
286 | "item": item
287 | });
288 | //console.log('change:' + index);
289 | }
290 | self.lastIndex = index;
291 | typeof force === 'function' && force();
292 | }, 0);
293 | };
294 |
295 | Picker.prototype.correctAngle = function (angle) {
296 | var self = this;
297 | if (angle < self.beginAngle) {
298 | return self.beginAngle;
299 | } else if (angle > self.endAngle) {
300 | return self.endAngle;
301 | } else {
302 | return angle;
303 | }
304 | };
305 |
306 | Picker.prototype.setItems = function (items) {
307 | var self = this;
308 | self.items = items || [];
309 | var buffer = [];
310 | self.items.forEach(function (item) {
311 | if (item !== null && item !== undefined) {
312 | buffer.push('' + (item.text || item) + '');
313 | }
314 | });
315 | self.list.innerHTML = buffer.join('');
316 | self.findElementItems();
317 | self.calcElementItemPostion();
318 | self.setAngle(self.correctAngle(self.list.angle));
319 | self.triggerChange(true);
320 | };
321 |
322 | Picker.prototype.getItems = function () {
323 | var self = this;
324 | return self.items;
325 | };
326 |
327 | Picker.prototype.getSelectedIndex = function () {
328 | var self = this;
329 | return parseInt((self.list.angle / self.itemAngle).toFixed(0));
330 | };
331 |
332 | Picker.prototype.setSelectedIndex = function (index, duration, callback) {
333 | var self = this;
334 | self.list.style.webkitTransition = '';
335 | var angle = self.correctAngle(self.itemAngle * index);
336 | if (duration && duration > 0) {
337 | var distAngle = angle - self.list.angle;
338 | self.scrollDistAngle(Date.now(), self.list.angle, distAngle, duration);
339 | } else {
340 | self.setAngle(angle);
341 | }
342 | self.triggerChange(callback);
343 | };
344 |
345 | Picker.prototype.getSelectedItem = function () {
346 | var self = this;
347 | return self.items[self.getSelectedIndex()];
348 | };
349 |
350 | Picker.prototype.getSelectedValue = function () {
351 | var self = this;
352 | return (self.items[self.getSelectedIndex()] || {}).value;
353 | };
354 |
355 | Picker.prototype.getSelectedText = function () {
356 | var self = this;
357 | return (self.items[self.getSelectedIndex()] || {}).text;
358 | };
359 |
360 | Picker.prototype.setSelectedValue = function (value, duration, callback) {
361 | var self = this;
362 | for (var index in self.items) {
363 | var item = self.items[index];
364 | if (item.value == value) {
365 | self.setSelectedIndex(index, duration, callback);
366 | return;
367 | }
368 | }
369 | };
370 |
371 | if ($.fn) {
372 | $.fn.picker = function (options) {
373 | //遍历选择的元素
374 | this.each(function (i, element) {
375 | if (element.picker) return;
376 | if (options) {
377 | element.picker = new Picker(element, options);
378 | } else {
379 | var optionsText = element.getAttribute('data-picker-options');
380 | var _options = optionsText ? JSON.parse(optionsText) : {};
381 | element.picker = new Picker(element, _options);
382 | }
383 | });
384 | return this[0] ? this[0].picker : null;
385 | };
386 |
387 | //自动初始化
388 | $.ready(function () {
389 | $('.mui-picker').picker();
390 | });
391 | }
392 | })(_mui2.default || window, window, document, undefined);
--------------------------------------------------------------------------------
/src/js/dtpicker.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 日期时间插件
3 | * varstion 1.0.5
4 | * by Houfeng
5 | * Houfeng@DCloud.io
6 | */
7 |
8 | import mui from './mui'
9 |
10 | (function($, document) {
11 |
12 | //创建 DOM
13 | $.dom = function(str) {
14 | if (typeof(str) !== 'string') {
15 | if ((str instanceof Array) || (str[0] && str.length)) {
16 | return [].slice.call(str);
17 | } else {
18 | return [str];
19 | }
20 | }
21 | if (!$.__create_dom_div__) {
22 | $.__create_dom_div__ = document.createElement('div');
23 | }
24 | $.__create_dom_div__.innerHTML = str;
25 | return [].slice.call($.__create_dom_div__.childNodes);
26 | };
27 |
28 | var domBuffer = '\
29 | \
33 |
年
月
日
时
分
\
34 |
\
35 |
\
36 |
\
37 |
\
38 |
\
40 |
\
41 |
\
42 |
\
43 |
\
44 |
\
45 |
\
46 |
\
48 |
\
49 |
\
50 |
\
51 |
\
52 |
\
53 |
\
54 |
\
56 |
\
57 |
\
58 |
\
59 |
\
60 |
\
61 |
\
62 |
\
64 |
\
65 |
\
66 |
\
67 |
\
68 |
\
69 |
\
70 |
\
72 |
\
73 |
\
74 |
\
75 |
\
76 |
';
77 |
78 | //plugin
79 | var DtPicker = $.DtPicker = $.Class.extend({
80 | init: function(options) {
81 | var self = this;
82 | var _picker = $.dom(domBuffer)[0];
83 | document.body.appendChild(_picker);
84 | $('[data-id*="picker"]', _picker).picker();
85 | var ui = self.ui = {
86 | picker: _picker,
87 | mask: $.createMask(),
88 | ok: $('[data-id="btn-ok"]', _picker)[0],
89 | cancel: $('[data-id="btn-cancel"]', _picker)[0],
90 | y: $('[data-id="picker-y"]', _picker)[0],
91 | m: $('[data-id="picker-m"]', _picker)[0],
92 | d: $('[data-id="picker-d"]', _picker)[0],
93 | h: $('[data-id="picker-h"]', _picker)[0],
94 | i: $('[data-id="picker-i"]', _picker)[0],
95 | labels: $('[data-id*="title-"]', _picker),
96 | };
97 | ui.cancel.addEventListener('tap', function() {
98 | self.hide();
99 | }, false);
100 | ui.ok.addEventListener('tap', function() {
101 | self.callback(self.getSelected());
102 | }, false);
103 | ui.y.addEventListener('change', function(e) { //目前的change事件容易导致级联触发
104 | if (self.options.beginMonth || self.options.endMonth) {
105 | self._createMonth();
106 | } else {
107 | self._createDay();
108 | }
109 | }, false);
110 | ui.m.addEventListener('change', function(e) {
111 | self._createDay();
112 | }, false);
113 | ui.d.addEventListener('change', function(e) {
114 | if (self.options.beginMonth || self.options.endMonth) { //仅提供了beginDate时,触发day,hours,minutes的change
115 | self._createHours();
116 | }
117 | }, false);
118 | ui.h.addEventListener('change', function(e) {
119 | if (self.options.beginMonth || self.options.endMonth) {
120 | self._createMinutes();
121 | }
122 | }, false);
123 |
124 | self._create(options);
125 | //防止滚动穿透
126 | self.ui.picker.addEventListener($.EVENT_START, function(event) {
127 | event.preventDefault();
128 | }, false);
129 | self.ui.picker.addEventListener($.EVENT_MOVE, function(event) {
130 | event.preventDefault();
131 | }, false);
132 | },
133 | getSelected: function() {
134 | var self = this;
135 | var ui = self.ui;
136 | var type = self.options.type;
137 | var selected = {
138 | type: type,
139 | y: ui.y.picker.getSelectedItem(),
140 | m: ui.m.picker.getSelectedItem(),
141 | d: ui.d.picker.getSelectedItem(),
142 | h: ui.h.picker.getSelectedItem(),
143 | i: ui.i.picker.getSelectedItem(),
144 | toString: function() {
145 | return this.value;
146 | }
147 | };
148 | switch (type) {
149 | case 'datetime':
150 | selected.value = selected.y.value + '-' + selected.m.value + '-' + selected.d.value + ' ' + selected.h.value + ':' + selected.i.value;
151 | selected.text = selected.y.text + '-' + selected.m.text + '-' + selected.d.text + ' ' + selected.h.text + ':' + selected.i.text;
152 | break;
153 | case 'date':
154 | selected.value = selected.y.value + '-' + selected.m.value + '-' + selected.d.value;
155 | selected.text = selected.y.text + '-' + selected.m.text + '-' + selected.d.text;
156 | break;
157 | case 'time':
158 | selected.value = selected.h.value + ':' + selected.i.value;
159 | selected.text = selected.h.text + ':' + selected.i.text;
160 | break;
161 | case 'month':
162 | selected.value = selected.y.value + '-' + selected.m.value;
163 | selected.text = selected.y.text + '-' + selected.m.text;
164 | break;
165 | case 'hour':
166 | selected.value = selected.y.value + '-' + selected.m.value + '-' + selected.d.value + ' ' + selected.h.value;
167 | selected.text = selected.y.text + '-' + selected.m.text + '-' + selected.d.text + ' ' + selected.h.text;
168 | break;
169 | }
170 | return selected;
171 | },
172 | setSelectedValue: function(value) {
173 | var self = this;
174 | var ui = self.ui;
175 | var parsedValue = self._parseValue(value);
176 | //TODO 嵌套过多,因为picker的change时间是异步(考虑到性能)的,所以为了保证change之后再setSelected,目前使用回调处理
177 | ui.y.picker.setSelectedValue(parsedValue.y, 0, function() {
178 | ui.m.picker.setSelectedValue(parsedValue.m, 0, function() {
179 | ui.d.picker.setSelectedValue(parsedValue.d, 0, function() {
180 | ui.h.picker.setSelectedValue(parsedValue.h, 0, function() {
181 | ui.i.picker.setSelectedValue(parsedValue.i, 0);
182 | });
183 | });
184 | });
185 | });
186 | },
187 | isLeapYear: function(year) {
188 | return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
189 | },
190 | _inArray: function(array, item) {
191 | for (var index in array) {
192 | var _item = array[index];
193 | if (_item === item) return true;
194 | }
195 | return false;
196 | },
197 | getDayNum: function(year, month) {
198 | var self = this;
199 | if (self._inArray([1, 3, 5, 7, 8, 10, 12], month)) {
200 | return 31;
201 | } else if (self._inArray([4, 6, 9, 11], month)) {
202 | return 30;
203 | } else if (self.isLeapYear(year)) {
204 | return 29;
205 | } else {
206 | return 28;
207 | }
208 | },
209 | _fill: function(num) {
210 | num = num.toString();
211 | if (num.length < 2) {
212 | num = 0 + num;
213 | }
214 | return num;
215 | },
216 | _isBeginYear: function() {
217 | return this.options.beginYear === parseInt(this.ui.y.picker.getSelectedValue());
218 | },
219 | _isBeginMonth: function() {
220 | return this.options.beginMonth && this._isBeginYear() && this.options.beginMonth === parseInt(this.ui.m.picker.getSelectedValue());
221 | },
222 | _isBeginDay: function() {
223 | return this._isBeginMonth() && this.options.beginDay === parseInt(this.ui.d.picker.getSelectedValue());
224 | },
225 | _isBeginHours: function() {
226 | return this._isBeginDay() && this.options.beginHours === parseInt(this.ui.h.picker.getSelectedValue());
227 | },
228 | _isEndYear: function() {
229 | return this.options.endYear === parseInt(this.ui.y.picker.getSelectedValue());
230 | },
231 | _isEndMonth: function() {
232 | return this.options.endMonth && this._isEndYear() && this.options.endMonth === parseInt(this.ui.m.picker.getSelectedValue());
233 | },
234 | _isEndDay: function() {
235 | return this._isEndMonth() && this.options.endDay === parseInt(this.ui.d.picker.getSelectedValue());
236 | },
237 | _isEndHours: function() {
238 | return this._isEndDay() && this.options.endHours === parseInt(this.ui.h.picker.getSelectedValue());
239 | },
240 | _createYear: function(current) {
241 | var self = this;
242 | var options = self.options;
243 | var ui = self.ui;
244 | //生成年列表
245 | var yArray = [];
246 | if (options.customData.y) {
247 | yArray = options.customData.y;
248 | } else {
249 | var yBegin = options.beginYear;
250 | var yEnd = options.endYear;
251 | for (var y = yBegin; y <= yEnd; y++) {
252 | yArray.push({
253 | text: y + '',
254 | value: y
255 | });
256 | }
257 | }
258 | ui.y.picker.setItems(yArray);
259 | //ui.y.picker.setSelectedValue(current);
260 | },
261 | _createMonth: function(current) {
262 | var self = this;
263 | var options = self.options;
264 | var ui = self.ui;
265 |
266 | //生成月列表
267 | var mArray = [];
268 | if (options.customData.m) {
269 | mArray = options.customData.m;
270 | } else {
271 | var m = options.beginMonth && self._isBeginYear() ? options.beginMonth : 1;
272 | var maxMonth = options.endMonth && self._isEndYear() ? options.endMonth : 12;
273 | for (; m <= maxMonth; m++) {
274 | var val = self._fill(m);
275 | mArray.push({
276 | text: val,
277 | value: val
278 | });
279 | }
280 | }
281 | ui.m.picker.setItems(mArray);
282 | //ui.m.picker.setSelectedValue(current);
283 | },
284 | _createDay: function(current) {
285 | var self = this;
286 | var options = self.options;
287 | var ui = self.ui;
288 |
289 | //生成日列表
290 | var dArray = [];
291 | if (options.customData.d) {
292 | dArray = options.customData.d;
293 | } else {
294 | var d = self._isBeginMonth() ? options.beginDay : 1;
295 | var maxDay = self._isEndMonth() ? options.endDay : self.getDayNum(parseInt(this.ui.y.picker.getSelectedValue()), parseInt(this.ui.m.picker.getSelectedValue()));
296 | for (; d <= maxDay; d++) {
297 | var val = self._fill(d);
298 | dArray.push({
299 | text: val,
300 | value: val
301 | });
302 | }
303 | }
304 | ui.d.picker.setItems(dArray);
305 | current = current || ui.d.picker.getSelectedValue();
306 | //ui.d.picker.setSelectedValue(current);
307 | },
308 | _createHours: function(current) {
309 | var self = this;
310 | var options = self.options;
311 | var ui = self.ui;
312 | //生成时列表
313 | var hArray = [];
314 | if (options.customData.h) {
315 | hArray = options.customData.h;
316 | } else {
317 | var h = self._isBeginDay() ? options.beginHours : 0;
318 | var maxHours = self._isEndDay() ? options.endHours : 23;
319 | for (; h <= maxHours; h++) {
320 | var val = self._fill(h);
321 | hArray.push({
322 | text: val,
323 | value: val
324 | });
325 | }
326 | }
327 | ui.h.picker.setItems(hArray);
328 | //ui.h.picker.setSelectedValue(current);
329 | },
330 | _createMinutes: function(current) {
331 | var self = this;
332 | var options = self.options;
333 | var ui = self.ui;
334 |
335 | //生成分列表
336 | var iArray = [];
337 | if (options.customData.i) {
338 | iArray = options.customData.i;
339 | } else {
340 | var i = self._isBeginHours() ? options.beginMinutes : 0;
341 | var maxMinutes = self._isEndHours() ? options.endMinutes : 59;
342 | for (; i <= maxMinutes; i++) {
343 | var val = self._fill(i);
344 | iArray.push({
345 | text: val,
346 | value: val
347 | });
348 | }
349 | }
350 | ui.i.picker.setItems(iArray);
351 | //ui.i.picker.setSelectedValue(current);
352 | },
353 | _setLabels: function() {
354 | var self = this;
355 | var options = self.options;
356 | var ui = self.ui;
357 | ui.labels.each(function(i, label) {
358 | label.innerText = options.labels[i];
359 | });
360 | },
361 | _setButtons: function() {
362 | var self = this;
363 | var options = self.options;
364 | var ui = self.ui;
365 | ui.cancel.innerText = options.buttons[0];
366 | ui.ok.innerText = options.buttons[1];
367 | },
368 | _parseValue: function(value) {
369 | var self = this;
370 | var rs = {};
371 | if (value) {
372 | var parts = value.replace(":", "-").replace(" ", "-").split("-");
373 | rs.y = parts[0];
374 | rs.m = parts[1];
375 | rs.d = parts[2];
376 | rs.h = parts[3];
377 | rs.i = parts[4];
378 | } else {
379 | var now = new Date();
380 | rs.y = now.getFullYear();
381 | rs.m = now.getMonth() + 1;
382 | rs.d = now.getDate();
383 | rs.h = now.getHours();
384 | rs.i = now.getMinutes();
385 | }
386 | return rs;
387 | },
388 | _create: function(options) {
389 | var self = this;
390 | options = options || {};
391 | options.labels = options.labels || ['年', '月', '日', '时', '分'];
392 | options.buttons = options.buttons || ['取消', '确定'];
393 | options.type = options.type || 'datetime';
394 | options.customData = options.customData || {};
395 | self.options = options;
396 | var now = new Date();
397 | var beginDate = options.beginDate;
398 | if (beginDate instanceof Date && !isNaN(beginDate.valueOf())) { //设定了开始日期
399 | options.beginYear = beginDate.getFullYear();
400 | options.beginMonth = beginDate.getMonth() + 1;
401 | options.beginDay = beginDate.getDate();
402 | options.beginHours = beginDate.getHours();
403 | options.beginMinutes = beginDate.getMinutes();
404 | }
405 | var endDate = options.endDate;
406 | if (endDate instanceof Date && !isNaN(endDate.valueOf())) { //设定了结束日期
407 | options.endYear = endDate.getFullYear();
408 | options.endMonth = endDate.getMonth() + 1;
409 | options.endDay = endDate.getDate();
410 | options.endHours = endDate.getHours();
411 | options.endMinutes = endDate.getMinutes();
412 | }
413 | options.beginYear = options.beginYear || (now.getFullYear() - 5);
414 | options.endYear = options.endYear || (now.getFullYear() + 5);
415 | var ui = self.ui;
416 | //设定label
417 | self._setLabels();
418 | self._setButtons();
419 | //设定类型
420 | ui.picker.setAttribute('data-type', options.type);
421 | //生成
422 | self._createYear();
423 | self._createMonth();
424 | self._createDay();
425 | self._createHours();
426 | self._createMinutes();
427 | //设定默认值
428 | self.setSelectedValue(options.value);
429 | },
430 | //显示
431 | show: function(callback) {
432 | var self = this;
433 | var ui = self.ui;
434 | self.callback = callback || $.noop;
435 | ui.mask.show();
436 | document.body.classList.add($.className('dtpicker-active-for-page'));
437 | ui.picker.classList.add($.className('active'));
438 | //处理物理返回键
439 | self.__back = $.back;
440 | $.back = function() {
441 | self.hide();
442 | };
443 | },
444 | hide: function() {
445 | var self = this;
446 | if (self.disposed) return;
447 | var ui = self.ui;
448 | ui.picker.classList.remove($.className('active'));
449 | ui.mask.close();
450 | document.body.classList.remove($.className('dtpicker-active-for-page'));
451 | //处理物理返回键
452 | $.back = self.__back;
453 | },
454 | dispose: function() {
455 | var self = this;
456 | self.hide();
457 | setTimeout(function() {
458 | self.ui.picker.parentNode.removeChild(self.ui.picker);
459 | for (var name in self) {
460 | self[name] = null;
461 | delete self[name];
462 | };
463 | self.disposed = true;
464 | }, 300);
465 | }
466 | });
467 |
468 | })(mui, document);
469 |
470 |
471 | export default mui.DtPicker
472 |
--------------------------------------------------------------------------------
/lib/js/dtpicker.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _mui = require('./mui');
8 |
9 | var _mui2 = _interopRequireDefault(_mui);
10 |
11 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12 |
13 | (function ($, document) {
14 |
15 | //创建 DOM
16 | $.dom = function (str) {
17 | if (typeof str !== 'string') {
18 | if (str instanceof Array || str[0] && str.length) {
19 | return [].slice.call(str);
20 | } else {
21 | return [str];
22 | }
23 | }
24 | if (!$.__create_dom_div__) {
25 | $.__create_dom_div__ = document.createElement('div');
26 | }
27 | $.__create_dom_div__.innerHTML = str;
28 | return [].slice.call($.__create_dom_div__.childNodes);
29 | };
30 |
31 | var domBuffer = '\
32 | \
36 |
年
月
日
时
分
\
37 |
\
38 |
\
39 |
\
40 |
\
41 |
\
43 |
\
44 |
\
45 |
\
46 |
\
47 |
\
48 |
\
49 |
\
51 |
\
52 |
\
53 |
\
54 |
\
55 |
\
56 |
\
57 |
\
59 |
\
60 |
\
61 |
\
62 |
\
63 |
\
64 |
\
65 |
\
67 |
\
68 |
\
69 |
\
70 |
\
71 |
\
72 |
\
73 |
\
75 |
\
76 |
\
77 |
\
78 |
\
79 |
';
80 |
81 | //plugin
82 | var DtPicker = $.DtPicker = $.Class.extend({
83 | init: function init(options) {
84 | var self = this;
85 | var _picker = $.dom(domBuffer)[0];
86 | document.body.appendChild(_picker);
87 | $('[data-id*="picker"]', _picker).picker();
88 | var ui = self.ui = {
89 | picker: _picker,
90 | mask: $.createMask(),
91 | ok: $('[data-id="btn-ok"]', _picker)[0],
92 | cancel: $('[data-id="btn-cancel"]', _picker)[0],
93 | y: $('[data-id="picker-y"]', _picker)[0],
94 | m: $('[data-id="picker-m"]', _picker)[0],
95 | d: $('[data-id="picker-d"]', _picker)[0],
96 | h: $('[data-id="picker-h"]', _picker)[0],
97 | i: $('[data-id="picker-i"]', _picker)[0],
98 | labels: $('[data-id*="title-"]', _picker)
99 | };
100 | ui.cancel.addEventListener('tap', function () {
101 | self.hide();
102 | }, false);
103 | ui.ok.addEventListener('tap', function () {
104 | self.callback(self.getSelected());
105 | }, false);
106 | ui.y.addEventListener('change', function (e) {
107 | //目前的change事件容易导致级联触发
108 | if (self.options.beginMonth || self.options.endMonth) {
109 | self._createMonth();
110 | } else {
111 | self._createDay();
112 | }
113 | }, false);
114 | ui.m.addEventListener('change', function (e) {
115 | self._createDay();
116 | }, false);
117 | ui.d.addEventListener('change', function (e) {
118 | if (self.options.beginMonth || self.options.endMonth) {
119 | //仅提供了beginDate时,触发day,hours,minutes的change
120 | self._createHours();
121 | }
122 | }, false);
123 | ui.h.addEventListener('change', function (e) {
124 | if (self.options.beginMonth || self.options.endMonth) {
125 | self._createMinutes();
126 | }
127 | }, false);
128 |
129 | self._create(options);
130 | //防止滚动穿透
131 | self.ui.picker.addEventListener($.EVENT_START, function (event) {
132 | event.preventDefault();
133 | }, false);
134 | self.ui.picker.addEventListener($.EVENT_MOVE, function (event) {
135 | event.preventDefault();
136 | }, false);
137 | },
138 | getSelected: function getSelected() {
139 | var self = this;
140 | var ui = self.ui;
141 | var type = self.options.type;
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 toString() {
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 | selected.value = selected.y.value + '-' + selected.m.value;
168 | selected.text = selected.y.text + '-' + selected.m.text;
169 | break;
170 | case 'hour':
171 | selected.value = selected.y.value + '-' + selected.m.value + '-' + selected.d.value + ' ' + selected.h.value;
172 | selected.text = selected.y.text + '-' + selected.m.text + '-' + selected.d.text + ' ' + selected.h.text;
173 | break;
174 | }
175 | return selected;
176 | },
177 | setSelectedValue: function setSelectedValue(value) {
178 | var self = this;
179 | var ui = self.ui;
180 | var parsedValue = self._parseValue(value);
181 | //TODO 嵌套过多,因为picker的change时间是异步(考虑到性能)的,所以为了保证change之后再setSelected,目前使用回调处理
182 | ui.y.picker.setSelectedValue(parsedValue.y, 0, function () {
183 | ui.m.picker.setSelectedValue(parsedValue.m, 0, function () {
184 | ui.d.picker.setSelectedValue(parsedValue.d, 0, function () {
185 | ui.h.picker.setSelectedValue(parsedValue.h, 0, function () {
186 | ui.i.picker.setSelectedValue(parsedValue.i, 0);
187 | });
188 | });
189 | });
190 | });
191 | },
192 | isLeapYear: function isLeapYear(year) {
193 | return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
194 | },
195 | _inArray: function _inArray(array, item) {
196 | for (var index in array) {
197 | var _item = array[index];
198 | if (_item === item) return true;
199 | }
200 | return false;
201 | },
202 | getDayNum: function getDayNum(year, month) {
203 | var self = this;
204 | if (self._inArray([1, 3, 5, 7, 8, 10, 12], month)) {
205 | return 31;
206 | } else if (self._inArray([4, 6, 9, 11], month)) {
207 | return 30;
208 | } else if (self.isLeapYear(year)) {
209 | return 29;
210 | } else {
211 | return 28;
212 | }
213 | },
214 | _fill: function _fill(num) {
215 | num = num.toString();
216 | if (num.length < 2) {
217 | num = 0 + num;
218 | }
219 | return num;
220 | },
221 | _isBeginYear: function _isBeginYear() {
222 | return this.options.beginYear === parseInt(this.ui.y.picker.getSelectedValue());
223 | },
224 | _isBeginMonth: function _isBeginMonth() {
225 | return this.options.beginMonth && this._isBeginYear() && this.options.beginMonth === parseInt(this.ui.m.picker.getSelectedValue());
226 | },
227 | _isBeginDay: function _isBeginDay() {
228 | return this._isBeginMonth() && this.options.beginDay === parseInt(this.ui.d.picker.getSelectedValue());
229 | },
230 | _isBeginHours: function _isBeginHours() {
231 | return this._isBeginDay() && this.options.beginHours === parseInt(this.ui.h.picker.getSelectedValue());
232 | },
233 | _isEndYear: function _isEndYear() {
234 | return this.options.endYear === parseInt(this.ui.y.picker.getSelectedValue());
235 | },
236 | _isEndMonth: function _isEndMonth() {
237 | return this.options.endMonth && this._isEndYear() && this.options.endMonth === parseInt(this.ui.m.picker.getSelectedValue());
238 | },
239 | _isEndDay: function _isEndDay() {
240 | return this._isEndMonth() && this.options.endDay === parseInt(this.ui.d.picker.getSelectedValue());
241 | },
242 | _isEndHours: function _isEndHours() {
243 | return this._isEndDay() && this.options.endHours === parseInt(this.ui.h.picker.getSelectedValue());
244 | },
245 | _createYear: function _createYear(current) {
246 | var self = this;
247 | var options = self.options;
248 | var ui = self.ui;
249 | //生成年列表
250 | var yArray = [];
251 | if (options.customData.y) {
252 | yArray = options.customData.y;
253 | } else {
254 | var yBegin = options.beginYear;
255 | var yEnd = options.endYear;
256 | for (var y = yBegin; y <= yEnd; y++) {
257 | yArray.push({
258 | text: y + '',
259 | value: y
260 | });
261 | }
262 | }
263 | ui.y.picker.setItems(yArray);
264 | //ui.y.picker.setSelectedValue(current);
265 | },
266 | _createMonth: function _createMonth(current) {
267 | var self = this;
268 | var options = self.options;
269 | var ui = self.ui;
270 |
271 | //生成月列表
272 | var mArray = [];
273 | if (options.customData.m) {
274 | mArray = options.customData.m;
275 | } else {
276 | var m = options.beginMonth && self._isBeginYear() ? options.beginMonth : 1;
277 | var maxMonth = options.endMonth && self._isEndYear() ? options.endMonth : 12;
278 | for (; m <= maxMonth; m++) {
279 | var val = self._fill(m);
280 | mArray.push({
281 | text: val,
282 | value: val
283 | });
284 | }
285 | }
286 | ui.m.picker.setItems(mArray);
287 | //ui.m.picker.setSelectedValue(current);
288 | },
289 | _createDay: function _createDay(current) {
290 | var self = this;
291 | var options = self.options;
292 | var ui = self.ui;
293 |
294 | //生成日列表
295 | var dArray = [];
296 | if (options.customData.d) {
297 | dArray = options.customData.d;
298 | } else {
299 | var d = self._isBeginMonth() ? options.beginDay : 1;
300 | var maxDay = self._isEndMonth() ? options.endDay : self.getDayNum(parseInt(this.ui.y.picker.getSelectedValue()), parseInt(this.ui.m.picker.getSelectedValue()));
301 | for (; d <= maxDay; d++) {
302 | var val = self._fill(d);
303 | dArray.push({
304 | text: val,
305 | value: val
306 | });
307 | }
308 | }
309 | ui.d.picker.setItems(dArray);
310 | current = current || ui.d.picker.getSelectedValue();
311 | //ui.d.picker.setSelectedValue(current);
312 | },
313 | _createHours: function _createHours(current) {
314 | var self = this;
315 | var options = self.options;
316 | var ui = self.ui;
317 | //生成时列表
318 | var hArray = [];
319 | if (options.customData.h) {
320 | hArray = options.customData.h;
321 | } else {
322 | var h = self._isBeginDay() ? options.beginHours : 0;
323 | var maxHours = self._isEndDay() ? options.endHours : 23;
324 | for (; h <= maxHours; h++) {
325 | var val = self._fill(h);
326 | hArray.push({
327 | text: val,
328 | value: val
329 | });
330 | }
331 | }
332 | ui.h.picker.setItems(hArray);
333 | //ui.h.picker.setSelectedValue(current);
334 | },
335 | _createMinutes: function _createMinutes(current) {
336 | var self = this;
337 | var options = self.options;
338 | var ui = self.ui;
339 |
340 | //生成分列表
341 | var iArray = [];
342 | if (options.customData.i) {
343 | iArray = options.customData.i;
344 | } else {
345 | var i = self._isBeginHours() ? options.beginMinutes : 0;
346 | var maxMinutes = self._isEndHours() ? options.endMinutes : 59;
347 | for (; i <= maxMinutes; i++) {
348 | var val = self._fill(i);
349 | iArray.push({
350 | text: val,
351 | value: val
352 | });
353 | }
354 | }
355 | ui.i.picker.setItems(iArray);
356 | //ui.i.picker.setSelectedValue(current);
357 | },
358 | _setLabels: function _setLabels() {
359 | var self = this;
360 | var options = self.options;
361 | var ui = self.ui;
362 | ui.labels.each(function (i, label) {
363 | label.innerText = options.labels[i];
364 | });
365 | },
366 | _setButtons: function _setButtons() {
367 | var self = this;
368 | var options = self.options;
369 | var ui = self.ui;
370 | ui.cancel.innerText = options.buttons[0];
371 | ui.ok.innerText = options.buttons[1];
372 | },
373 | _parseValue: function _parseValue(value) {
374 | var self = this;
375 | var rs = {};
376 | if (value) {
377 | var parts = value.replace(":", "-").replace(" ", "-").split("-");
378 | rs.y = parts[0];
379 | rs.m = parts[1];
380 | rs.d = parts[2];
381 | rs.h = parts[3];
382 | rs.i = parts[4];
383 | } else {
384 | var now = new Date();
385 | rs.y = now.getFullYear();
386 | rs.m = now.getMonth() + 1;
387 | rs.d = now.getDate();
388 | rs.h = now.getHours();
389 | rs.i = now.getMinutes();
390 | }
391 | return rs;
392 | },
393 | _create: function _create(options) {
394 | var self = this;
395 | options = options || {};
396 | options.labels = options.labels || ['年', '月', '日', '时', '分'];
397 | options.buttons = options.buttons || ['取消', '确定'];
398 | options.type = options.type || 'datetime';
399 | options.customData = options.customData || {};
400 | self.options = options;
401 | var now = new Date();
402 | var beginDate = options.beginDate;
403 | if (beginDate instanceof Date && !isNaN(beginDate.valueOf())) {
404 | //设定了开始日期
405 | options.beginYear = beginDate.getFullYear();
406 | options.beginMonth = beginDate.getMonth() + 1;
407 | options.beginDay = beginDate.getDate();
408 | options.beginHours = beginDate.getHours();
409 | options.beginMinutes = beginDate.getMinutes();
410 | }
411 | var endDate = options.endDate;
412 | if (endDate instanceof Date && !isNaN(endDate.valueOf())) {
413 | //设定了结束日期
414 | options.endYear = endDate.getFullYear();
415 | options.endMonth = endDate.getMonth() + 1;
416 | options.endDay = endDate.getDate();
417 | options.endHours = endDate.getHours();
418 | options.endMinutes = endDate.getMinutes();
419 | }
420 | options.beginYear = options.beginYear || now.getFullYear() - 5;
421 | options.endYear = options.endYear || now.getFullYear() + 5;
422 | var ui = self.ui;
423 | //设定label
424 | self._setLabels();
425 | self._setButtons();
426 | //设定类型
427 | ui.picker.setAttribute('data-type', options.type);
428 | //生成
429 | self._createYear();
430 | self._createMonth();
431 | self._createDay();
432 | self._createHours();
433 | self._createMinutes();
434 | //设定默认值
435 | self.setSelectedValue(options.value);
436 | },
437 | //显示
438 | show: function show(callback) {
439 | var self = this;
440 | var ui = self.ui;
441 | self.callback = callback || $.noop;
442 | ui.mask.show();
443 | document.body.classList.add($.className('dtpicker-active-for-page'));
444 | ui.picker.classList.add($.className('active'));
445 | //处理物理返回键
446 | self.__back = $.back;
447 | $.back = function () {
448 | self.hide();
449 | };
450 | },
451 | hide: function hide() {
452 | var self = this;
453 | if (self.disposed) return;
454 | var ui = self.ui;
455 | ui.picker.classList.remove($.className('active'));
456 | ui.mask.close();
457 | document.body.classList.remove($.className('dtpicker-active-for-page'));
458 | //处理物理返回键
459 | $.back = self.__back;
460 | },
461 | dispose: function dispose() {
462 | var self = this;
463 | self.hide();
464 | setTimeout(function () {
465 | self.ui.picker.parentNode.removeChild(self.ui.picker);
466 | for (var name in self) {
467 | self[name] = null;
468 | delete self[name];
469 | };
470 | self.disposed = true;
471 | }, 300);
472 | }
473 | });
474 | })(_mui2.default, document); /**
475 | * 日期时间插件
476 | * varstion 1.0.5
477 | * by Houfeng
478 | * Houfeng@DCloud.io
479 | */
480 |
481 | exports.default = _mui2.default.DtPicker;
--------------------------------------------------------------------------------
/example/lib/city-data.js:
--------------------------------------------------------------------------------
1 | module.exports = [{
2 | value: '110000',
3 | text: '北京市',
4 | children: [{
5 | value: "110101",
6 | text: "东城区"
7 | }, {
8 | value: "110102",
9 | text: "西城区"
10 | }, {
11 | value: "110103",
12 | text: "崇文区"
13 | }, {
14 | value: "110104",
15 | text: "宣武区"
16 | }, {
17 | value: "110105",
18 | text: "朝阳区"
19 | }, {
20 | value: "110106",
21 | text: "丰台区"
22 | }, {
23 | value: "110107",
24 | text: "石景山区"
25 | }, {
26 | value: "110108",
27 | text: "海淀区"
28 | }, {
29 | value: "110109",
30 | text: "门头沟区"
31 | }, {
32 | value: "110111",
33 | text: "房山区"
34 | }, {
35 | value: "110112",
36 | text: "通州区"
37 | }, {
38 | value: "110113",
39 | text: "顺义区"
40 | }, {
41 | value: "110114",
42 | text: "昌平区"
43 | }, {
44 | value: "110115",
45 | text: "大兴区"
46 | }, {
47 | value: "110116",
48 | text: "怀柔区"
49 | }, {
50 | value: "110117",
51 | text: "平谷区"
52 | }, {
53 | value: "110228",
54 | text: "密云县"
55 | }, {
56 | value: "110229",
57 | text: "延庆县"
58 | }, {
59 | value: "110230",
60 | text: "其它区"
61 | }]
62 | }, {
63 | value: '120000',
64 | text: '天津市',
65 | children: [{
66 | value: "120101",
67 | text: "和平区"
68 | }, {
69 | value: "120102",
70 | text: "河东区"
71 | }, {
72 | value: "120103",
73 | text: "河西区"
74 | }, {
75 | value: "120104",
76 | text: "南开区"
77 | }, {
78 | value: "120105",
79 | text: "河北区"
80 | }, {
81 | value: "120106",
82 | text: "红桥区"
83 | }, {
84 | value: "120107",
85 | text: "塘沽区"
86 | }, {
87 | value: "120108",
88 | text: "汉沽区"
89 | }, {
90 | value: "120109",
91 | text: "大港区"
92 | }, {
93 | value: "120110",
94 | text: "东丽区"
95 | }, {
96 | value: "120111",
97 | text: "西青区"
98 | }, {
99 | value: "120112",
100 | text: "津南区"
101 | }, {
102 | value: "120113",
103 | text: "北辰区"
104 | }, {
105 | value: "120114",
106 | text: "武清区"
107 | }, {
108 | value: "120115",
109 | text: "宝坻区"
110 | }, {
111 | value: "120116",
112 | text: "滨海新区"
113 | }, {
114 | value: "120221",
115 | text: "宁河县"
116 | }, {
117 | value: "120223",
118 | text: "静海县"
119 | }, {
120 | value: "120225",
121 | text: "蓟县"
122 | }, {
123 | value: "120226",
124 | text: "其它区"
125 | }]
126 | }, {
127 | value: '130000',
128 | text: '河北省',
129 | children: [{
130 | value: "130100",
131 | text: "石家庄市"
132 | }, {
133 | value: "130200",
134 | text: "唐山市"
135 | }, {
136 | value: "130300",
137 | text: "秦皇岛市"
138 | }, {
139 | value: "130400",
140 | text: "邯郸市"
141 | }, {
142 | value: "130500",
143 | text: "邢台市"
144 | }, {
145 | value: "130600",
146 | text: "保定市"
147 | }, {
148 | value: "130700",
149 | text: "张家口市"
150 | }, {
151 | value: "130800",
152 | text: "承德市"
153 | }, {
154 | value: "130900",
155 | text: "沧州市"
156 | }, {
157 | value: "131000",
158 | text: "廊坊市"
159 | }, {
160 | value: "131100",
161 | text: "衡水市"
162 | }]
163 | }, {
164 | value: '140000',
165 | text: '山西省',
166 | children: [{
167 | value: "140100",
168 | text: "太原市"
169 | }, {
170 | value: "140200",
171 | text: "大同市"
172 | }, {
173 | value: "140300",
174 | text: "阳泉市"
175 | }, {
176 | value: "140400",
177 | text: "长治市"
178 | }, {
179 | value: "140500",
180 | text: "晋城市"
181 | }, {
182 | value: "140600",
183 | text: "朔州市"
184 | }, {
185 | value: "140700",
186 | text: "晋中市"
187 | }, {
188 | value: "140800",
189 | text: "运城市"
190 | }, {
191 | value: "140900",
192 | text: "忻州市"
193 | }, {
194 | value: "141000",
195 | text: "临汾市"
196 | }, {
197 | value: "141100",
198 | text: "吕梁市"
199 | }]
200 | }, {
201 | value: '150000',
202 | text: '内蒙古',
203 | children: [{
204 | value: "150100",
205 | text: "呼和浩特市"
206 | }, {
207 | value: "150200",
208 | text: "包头市"
209 | }, {
210 | value: "150300",
211 | text: "乌海市"
212 | }, {
213 | value: "150400",
214 | text: "赤峰市"
215 | }, {
216 | value: "150500",
217 | text: "通辽市"
218 | }, {
219 | value: "150600",
220 | text: "鄂尔多斯市"
221 | }, {
222 | value: "150700",
223 | text: "呼伦贝尔市"
224 | }, {
225 | value: "150800",
226 | text: "巴彦淖尔市"
227 | }, {
228 | value: "150900",
229 | text: "乌兰察布市"
230 | }, {
231 | value: "152200",
232 | text: "兴安盟"
233 | }, {
234 | value: "152500",
235 | text: "锡林郭勒盟"
236 | }, {
237 | value: "152900",
238 | text: "阿拉善盟"
239 | }]
240 | }, {
241 | value: '210000',
242 | text: '辽宁省',
243 | children: [{
244 | value: "210100",
245 | text: "沈阳市"
246 | }, {
247 | value: "210200",
248 | text: "大连市"
249 | }, {
250 | value: "210300",
251 | text: "鞍山市"
252 | }, {
253 | value: "210400",
254 | text: "抚顺市"
255 | }, {
256 | value: "210500",
257 | text: "本溪市"
258 | }, {
259 | value: "210600",
260 | text: "丹东市"
261 | }, {
262 | value: "210700",
263 | text: "锦州市"
264 | }, {
265 | value: "210800",
266 | text: "营口市"
267 | }, {
268 | value: "210900",
269 | text: "阜新市"
270 | }, {
271 | value: "211000",
272 | text: "辽阳市"
273 | }, {
274 | value: "211100",
275 | text: "盘锦市"
276 | }, {
277 | value: "211200",
278 | text: "铁岭市"
279 | }, {
280 | value: "211300",
281 | text: "朝阳市"
282 | }, {
283 | value: "211400",
284 | text: "葫芦岛市"
285 | }]
286 | }, {
287 | value: '220000',
288 | text: '吉林省',
289 | children: [{
290 | value: "220100",
291 | text: "长春市"
292 | }, {
293 | value: "220200",
294 | text: "吉林市"
295 | }, {
296 | value: "220300",
297 | text: "四平市"
298 | }, {
299 | value: "220400",
300 | text: "辽源市"
301 | }, {
302 | value: "220500",
303 | text: "通化市"
304 | }, {
305 | value: "220600",
306 | text: "白山市"
307 | }, {
308 | value: "220700",
309 | text: "松原市"
310 | }, {
311 | value: "220800",
312 | text: "白城市"
313 | }, {
314 | value: "222400",
315 | text: "延边朝鲜族自治州"
316 | }]
317 | }, {
318 | value: '230000',
319 | text: '黑龙江省',
320 | children: [{
321 | value: "230100",
322 | text: "哈尔滨市"
323 | }, {
324 | value: "230200",
325 | text: "齐齐哈尔市"
326 | }, {
327 | value: "230300",
328 | text: "鸡西市"
329 | }, {
330 | value: "230400",
331 | text: "鹤岗市"
332 | }, {
333 | value: "230500",
334 | text: "双鸭山市"
335 | }, {
336 | value: "230600",
337 | text: "大庆市"
338 | }, {
339 | value: "230700",
340 | text: "伊春市"
341 | }, {
342 | value: "230800",
343 | text: "佳木斯市"
344 | }, {
345 | value: "230900",
346 | text: "七台河市"
347 | }, {
348 | value: "231000",
349 | text: "牡丹江市"
350 | }, {
351 | value: "231100",
352 | text: "黑河市"
353 | }, {
354 | value: "231200",
355 | text: "绥化市"
356 | }, {
357 | value: "232700",
358 | text: "大兴安岭地区"
359 | }]
360 | }, {
361 | value: '310000',
362 | text: '上海市',
363 | children: [{
364 | value: "310101",
365 | text: "黄浦区"
366 | }, {
367 | value: "310103",
368 | text: "卢湾区"
369 | }, {
370 | value: "310104",
371 | text: "徐汇区"
372 | }, {
373 | value: "310105",
374 | text: "长宁区"
375 | }, {
376 | value: "310106",
377 | text: "静安区"
378 | }, {
379 | value: "310107",
380 | text: "普陀区"
381 | }, {
382 | value: "310108",
383 | text: "闸北区"
384 | }, {
385 | value: "310109",
386 | text: "虹口区"
387 | }, {
388 | value: "310110",
389 | text: "杨浦区"
390 | }, {
391 | value: "310112",
392 | text: "闵行区"
393 | }, {
394 | value: "310113",
395 | text: "宝山区"
396 | }, {
397 | value: "310114",
398 | text: "嘉定区"
399 | }, {
400 | value: "310115",
401 | text: "浦东新区"
402 | }, {
403 | value: "310116",
404 | text: "金山区"
405 | }, {
406 | value: "310117",
407 | text: "松江区"
408 | }, {
409 | value: "310118",
410 | text: "青浦区"
411 | }, {
412 | value: "310119",
413 | text: "南汇区"
414 | }, {
415 | value: "310120",
416 | text: "奉贤区"
417 | }, {
418 | value: "310152",
419 | text: "川沙区"
420 | }, {
421 | value: "310230",
422 | text: "崇明县"
423 | }, {
424 | value: "310231",
425 | text: "其它区"
426 | }]
427 | }, {
428 | value: '320000',
429 | text: '江苏省',
430 | children: [{
431 | value: "320100",
432 | text: "南京市"
433 | }, {
434 | value: "320200",
435 | text: "无锡市"
436 | }, {
437 | value: "320300",
438 | text: "徐州市"
439 | }, {
440 | value: "320400",
441 | text: "常州市"
442 | }, {
443 | value: "320500",
444 | text: "苏州市"
445 | }, {
446 | value: "320600",
447 | text: "南通市"
448 | }, {
449 | value: "320700",
450 | text: "连云港市"
451 | }, {
452 | value: "320800",
453 | text: "淮安市"
454 | }, {
455 | value: "320900",
456 | text: "盐城市"
457 | }, {
458 | value: "321000",
459 | text: "扬州市"
460 | }, {
461 | value: "321100",
462 | text: "镇江市"
463 | }, {
464 | value: "321200",
465 | text: "泰州市"
466 | }, {
467 | value: "321300",
468 | text: "宿迁市"
469 | }]
470 | }, {
471 | value: '330000',
472 | text: '浙江省',
473 | children: [{
474 | value: "330100",
475 | text: "杭州市"
476 | }, {
477 | value: "330200",
478 | text: "宁波市"
479 | }, {
480 | value: "330300",
481 | text: "温州市"
482 | }, {
483 | value: "330400",
484 | text: "嘉兴市"
485 | }, {
486 | value: "330500",
487 | text: "湖州市"
488 | }, {
489 | value: "330600",
490 | text: "绍兴市"
491 | }, {
492 | value: "330700",
493 | text: "金华市"
494 | }, {
495 | value: "330800",
496 | text: "衢州市"
497 | }, {
498 | value: "330900",
499 | text: "舟山市"
500 | }, {
501 | value: "331000",
502 | text: "台州市"
503 | }, {
504 | value: "331100",
505 | text: "丽水市"
506 | }]
507 | }, {
508 | value: '340000',
509 | text: '安徽省',
510 | children: [{
511 | value: "340100",
512 | text: "合肥市"
513 | }, {
514 | value: "340200",
515 | text: "芜湖市"
516 | }, {
517 | value: "340300",
518 | text: "蚌埠市"
519 | }, {
520 | value: "340400",
521 | text: "淮南市"
522 | }, {
523 | value: "340500",
524 | text: "马鞍山市"
525 | }, {
526 | value: "340600",
527 | text: "淮北市"
528 | }, {
529 | value: "340700",
530 | text: "铜陵市"
531 | }, {
532 | value: "340800",
533 | text: "安庆市"
534 | }, {
535 | value: "341000",
536 | text: "黄山市"
537 | }, {
538 | value: "341100",
539 | text: "滁州市"
540 | }, {
541 | value: "341200",
542 | text: "阜阳市"
543 | }, {
544 | value: "341300",
545 | text: "宿州市"
546 | }, {
547 | value: "341500",
548 | text: "六安市"
549 | }, {
550 | value: "341600",
551 | text: "亳州市"
552 | }, {
553 | value: "341700",
554 | text: "池州市"
555 | }, {
556 | value: "341800",
557 | text: "宣城市"
558 | }]
559 | }, {
560 | value: '350000',
561 | text: '福建省',
562 | children: [{
563 | value: "350100",
564 | text: "福州市"
565 | }, {
566 | value: "350200",
567 | text: "厦门市"
568 | }, {
569 | value: "350300",
570 | text: "莆田市"
571 | }, {
572 | value: "350400",
573 | text: "三明市"
574 | }, {
575 | value: "350500",
576 | text: "泉州市"
577 | }, {
578 | value: "350600",
579 | text: "漳州市"
580 | }, {
581 | value: "350700",
582 | text: "南平市"
583 | }, {
584 | value: "350800",
585 | text: "龙岩市"
586 | }, {
587 | value: "350900",
588 | text: "宁德市"
589 | }]
590 | }, {
591 | value: '360000',
592 | text: '江西省',
593 | children: [{
594 | value: "360100",
595 | text: "南昌市"
596 | }, {
597 | value: "360200",
598 | text: "景德镇市"
599 | }, {
600 | value: "360300",
601 | text: "萍乡市"
602 | }, {
603 | value: "360400",
604 | text: "九江市"
605 | }, {
606 | value: "360500",
607 | text: "新余市"
608 | }, {
609 | value: "360600",
610 | text: "鹰潭市"
611 | }, {
612 | value: "360700",
613 | text: "赣州市"
614 | }, {
615 | value: "360800",
616 | text: "吉安市"
617 | }, {
618 | value: "360900",
619 | text: "宜春市"
620 | }, {
621 | value: "361000",
622 | text: "抚州市"
623 | }, {
624 | value: "361100",
625 | text: "上饶市"
626 | }]
627 | }, {
628 | value: '370000',
629 | text: '山东省',
630 | children: [{
631 | value: "370100",
632 | text: "济南市"
633 | }, {
634 | value: "370200",
635 | text: "青岛市"
636 | }, {
637 | value: "370300",
638 | text: "淄博市"
639 | }, {
640 | value: "370400",
641 | text: "枣庄市"
642 | }, {
643 | value: "370500",
644 | text: "东营市"
645 | }, {
646 | value: "370600",
647 | text: "烟台市"
648 | }, {
649 | value: "370700",
650 | text: "潍坊市"
651 | }, {
652 | value: "370800",
653 | text: "济宁市"
654 | }, {
655 | value: "370900",
656 | text: "泰安市"
657 | }, {
658 | value: "371000",
659 | text: "威海市"
660 | }, {
661 | value: "371100",
662 | text: "日照市"
663 | }, {
664 | value: "371200",
665 | text: "莱芜市"
666 | }, {
667 | value: "371300",
668 | text: "临沂市"
669 | }, {
670 | value: "371400",
671 | text: "德州市"
672 | }, {
673 | value: "371500",
674 | text: "聊城市"
675 | }, {
676 | value: "371600",
677 | text: "滨州市"
678 | }, {
679 | value: "371700",
680 | text: "菏泽市"
681 | }]
682 | }, {
683 | value: '410000',
684 | text: '河南省',
685 | children: [{
686 | value: "410100",
687 | text: "郑州市"
688 | }, {
689 | value: "410200",
690 | text: "开封市"
691 | }, {
692 | value: "410300",
693 | text: "洛阳市"
694 | }, {
695 | value: "410400",
696 | text: "平顶山市"
697 | }, {
698 | value: "410500",
699 | text: "安阳市"
700 | }, {
701 | value: "410600",
702 | text: "鹤壁市"
703 | }, {
704 | value: "410700",
705 | text: "新乡市"
706 | }, {
707 | value: "410800",
708 | text: "焦作市"
709 | }, {
710 | value: "410881",
711 | text: "济源市"
712 | }, {
713 | value: "410900",
714 | text: "濮阳市"
715 | }, {
716 | value: "411000",
717 | text: "许昌市"
718 | }, {
719 | value: "411100",
720 | text: "漯河市"
721 | }, {
722 | value: "411200",
723 | text: "三门峡市"
724 | }, {
725 | value: "411300",
726 | text: "南阳市"
727 | }, {
728 | value: "411400",
729 | text: "商丘市"
730 | }, {
731 | value: "411500",
732 | text: "信阳市"
733 | }, {
734 | value: "411600",
735 | text: "周口市"
736 | }, {
737 | value: "411700",
738 | text: "驻马店市"
739 | }]
740 | }, {
741 | value: '420000',
742 | text: '湖北省',
743 | children: [{
744 | value: "420100",
745 | text: "武汉市"
746 | }, {
747 | value: "420200",
748 | text: "黄石市"
749 | }, {
750 | value: "420300",
751 | text: "十堰市"
752 | }, {
753 | value: "420500",
754 | text: "宜昌市"
755 | }, {
756 | value: "420600",
757 | text: "襄阳市"
758 | }, {
759 | value: "420700",
760 | text: "鄂州市"
761 | }, {
762 | value: "420800",
763 | text: "荆门市"
764 | }, {
765 | value: "420900",
766 | text: "孝感市"
767 | }, {
768 | value: "421000",
769 | text: "荆州市"
770 | }, {
771 | value: "421100",
772 | text: "黄冈市"
773 | }, {
774 | value: "421200",
775 | text: "咸宁市"
776 | }, {
777 | value: "421300",
778 | text: "随州市"
779 | }, {
780 | value: "422800",
781 | text: "恩施土家族苗族自治州"
782 | }, {
783 | value: "429004",
784 | text: "仙桃市"
785 | }, {
786 | value: "429005",
787 | text: "潜江市"
788 | }, {
789 | value: "429006",
790 | text: "天门市"
791 | }, {
792 | value: "429021",
793 | text: "神农架林区"
794 | }]
795 | }, {
796 | value: '430000',
797 | text: '湖南省',
798 | children: [{
799 | value: "430100",
800 | text: "长沙市"
801 | }, {
802 | value: "430200",
803 | text: "株洲市"
804 | }, {
805 | value: "430300",
806 | text: "湘潭市"
807 | }, {
808 | value: "430400",
809 | text: "衡阳市"
810 | }, {
811 | value: "430500",
812 | text: "邵阳市"
813 | }, {
814 | value: "430600",
815 | text: "岳阳市"
816 | }, {
817 | value: "430700",
818 | text: "常德市"
819 | }, {
820 | value: "430800",
821 | text: "张家界市"
822 | }, {
823 | value: "430900",
824 | text: "益阳市"
825 | }, {
826 | value: "431000",
827 | text: "郴州市"
828 | }, {
829 | value: "431100",
830 | text: "永州市"
831 | }, {
832 | value: "431200",
833 | text: "怀化市"
834 | }, {
835 | value: "431300",
836 | text: "娄底市"
837 | }, {
838 | value: "433100",
839 | text: "湘西土家族苗族自治州"
840 | }]
841 | }, {
842 | value: '440000',
843 | text: '广东省',
844 | children: [{
845 | value: "440100",
846 | text: "广州市"
847 | }, {
848 | value: "440200",
849 | text: "韶关市"
850 | }, {
851 | value: "440300",
852 | text: "深圳市"
853 | }, {
854 | value: "440400",
855 | text: "珠海市"
856 | }, {
857 | value: "440500",
858 | text: "汕头市"
859 | }, {
860 | value: "440600",
861 | text: "佛山市"
862 | }, {
863 | value: "440700",
864 | text: "江门市"
865 | }, {
866 | value: "440800",
867 | text: "湛江市"
868 | }, {
869 | value: "440900",
870 | text: "茂名市"
871 | }, {
872 | value: "441200",
873 | text: "肇庆市"
874 | }, {
875 | value: "441300",
876 | text: "惠州市"
877 | }, {
878 | value: "441400",
879 | text: "梅州市"
880 | }, {
881 | value: "441500",
882 | text: "汕尾市"
883 | }, {
884 | value: "441600",
885 | text: "河源市"
886 | }, {
887 | value: "441700",
888 | text: "阳江市"
889 | }, {
890 | value: "441800",
891 | text: "清远市"
892 | }, {
893 | value: "441900",
894 | text: "东莞市"
895 | }, {
896 | value: "442000",
897 | text: "中山市"
898 | }, {
899 | value: "445100",
900 | text: "潮州市"
901 | }, {
902 | value: "445200",
903 | text: "揭阳市"
904 | }, {
905 | value: "445300",
906 | text: "云浮市"
907 | }]
908 | }, {
909 | value: '450000',
910 | text: '广西壮族',
911 | children: [{
912 | value: "450100",
913 | text: "南宁市"
914 | }, {
915 | value: "450200",
916 | text: "柳州市"
917 | }, {
918 | value: "450300",
919 | text: "桂林市"
920 | }, {
921 | value: "450400",
922 | text: "梧州市"
923 | }, {
924 | value: "450500",
925 | text: "北海市"
926 | }, {
927 | value: "450600",
928 | text: "防城港市"
929 | }, {
930 | value: "450700",
931 | text: "钦州市"
932 | }, {
933 | value: "450800",
934 | text: "贵港市"
935 | }, {
936 | value: "450900",
937 | text: "玉林市"
938 | }, {
939 | value: "451000",
940 | text: "百色市"
941 | }, {
942 | value: "451100",
943 | text: "贺州市"
944 | }, {
945 | value: "451200",
946 | text: "河池市"
947 | }, {
948 | value: "451300",
949 | text: "来宾市"
950 | }, {
951 | value: "451400",
952 | text: "崇左市"
953 | }]
954 | }, {
955 | value: '460000',
956 | text: '海南省',
957 | children: [{
958 | value: "460100",
959 | text: "海口市"
960 | }, {
961 | value: "460200",
962 | text: "三亚市"
963 | }, {
964 | value: "469001",
965 | text: "五指山市"
966 | }, {
967 | value: "469002",
968 | text: "琼海市"
969 | }, {
970 | value: "469003",
971 | text: "儋州市"
972 | }, {
973 | value: "469005",
974 | text: "文昌市"
975 | }, {
976 | value: "469006",
977 | text: "万宁市"
978 | }, {
979 | value: "469007",
980 | text: "东方市"
981 | }, {
982 | value: "469025",
983 | text: "定安县"
984 | }, {
985 | value: "469026",
986 | text: "屯昌县"
987 | }, {
988 | value: "469027",
989 | text: "澄迈县"
990 | }, {
991 | value: "469028",
992 | text: "临高县"
993 | }, {
994 | value: "469030",
995 | text: "白沙黎族自治县"
996 | }, {
997 | value: "469031",
998 | text: "昌江黎族自治县"
999 | }, {
1000 | value: "469033",
1001 | text: "乐东黎族自治县"
1002 | }, {
1003 | value: "469034",
1004 | text: "陵水黎族自治县"
1005 | }, {
1006 | value: "469035",
1007 | text: "保亭黎族苗族自治县"
1008 | }, {
1009 | value: "469036",
1010 | text: "琼中黎族苗族自治县"
1011 | }, {
1012 | value: "469037",
1013 | text: "西沙群岛"
1014 | }, {
1015 | value: "469038",
1016 | text: "南沙群岛"
1017 | }, {
1018 | value: "469039",
1019 | text: "中沙群岛的岛礁及其海域"
1020 | }]
1021 | }, {
1022 | value: '500000',
1023 | text: '重庆',
1024 | children: [{
1025 | value: "500101",
1026 | text: "万州区"
1027 | }, {
1028 | value: "500102",
1029 | text: "涪陵区"
1030 | }, {
1031 | value: "500103",
1032 | text: "渝中区"
1033 | }, {
1034 | value: "500104",
1035 | text: "大渡口区"
1036 | }, {
1037 | value: "500105",
1038 | text: "江北区"
1039 | }, {
1040 | value: "500106",
1041 | text: "沙坪坝区"
1042 | }, {
1043 | value: "500107",
1044 | text: "九龙坡区"
1045 | }, {
1046 | value: "500108",
1047 | text: "南岸区"
1048 | }, {
1049 | value: "500109",
1050 | text: "北碚区"
1051 | }, {
1052 | value: "500110",
1053 | text: "万盛区"
1054 | }, {
1055 | value: "500111",
1056 | text: "双桥区"
1057 | }, {
1058 | value: "500112",
1059 | text: "渝北区"
1060 | }, {
1061 | value: "500113",
1062 | text: "巴南区"
1063 | }, {
1064 | value: "500114",
1065 | text: "黔江区"
1066 | }, {
1067 | value: "500115",
1068 | text: "长寿区"
1069 | }, {
1070 | value: "500222",
1071 | text: "綦江县"
1072 | }, {
1073 | value: "500223",
1074 | text: "潼南县"
1075 | }, {
1076 | value: "500224",
1077 | text: "铜梁县"
1078 | }, {
1079 | value: "500225",
1080 | text: "大足县"
1081 | }, {
1082 | value: "500226",
1083 | text: "荣昌县"
1084 | }, {
1085 | value: "500227",
1086 | text: "璧山县"
1087 | }, {
1088 | value: "500228",
1089 | text: "梁平县"
1090 | }, {
1091 | value: "500229",
1092 | text: "城口县"
1093 | }, {
1094 | value: "500230",
1095 | text: "丰都县"
1096 | }, {
1097 | value: "500231",
1098 | text: "垫江县"
1099 | }, {
1100 | value: "500232",
1101 | text: "武隆县"
1102 | }, {
1103 | value: "500233",
1104 | text: "忠县"
1105 | }, {
1106 | value: "500234",
1107 | text: "开县"
1108 | }, {
1109 | value: "500235",
1110 | text: "云阳县"
1111 | }, {
1112 | value: "500236",
1113 | text: "奉节县"
1114 | }, {
1115 | value: "500237",
1116 | text: "巫山县"
1117 | }, {
1118 | value: "500238",
1119 | text: "巫溪县"
1120 | }, {
1121 | value: "500240",
1122 | text: "石柱土家族自治县"
1123 | }, {
1124 | value: "500241",
1125 | text: "秀山土家族苗族自治县"
1126 | }, {
1127 | value: "500242",
1128 | text: "酉阳土家族苗族自治县"
1129 | }, {
1130 | value: "500243",
1131 | text: "彭水苗族土家族自治县"
1132 | }, {
1133 | value: "500381",
1134 | text: "江津区"
1135 | }, {
1136 | value: "500382",
1137 | text: "合川区"
1138 | }, {
1139 | value: "500383",
1140 | text: "永川区"
1141 | }, {
1142 | value: "500384",
1143 | text: "南川区"
1144 | }, {
1145 | value: "500385",
1146 | text: "其它区"
1147 | }]
1148 | }, {
1149 | value: '510000',
1150 | text: '四川省',
1151 | children: [{
1152 | value: "510100",
1153 | text: "成都市"
1154 | }, {
1155 | value: "510300",
1156 | text: "自贡市"
1157 | }, {
1158 | value: "510400",
1159 | text: "攀枝花市"
1160 | }, {
1161 | value: "510500",
1162 | text: "泸州市"
1163 | }, {
1164 | value: "510600",
1165 | text: "德阳市"
1166 | }, {
1167 | value: "510700",
1168 | text: "绵阳市"
1169 | }, {
1170 | value: "510800",
1171 | text: "广元市"
1172 | }, {
1173 | value: "510900",
1174 | text: "遂宁市"
1175 | }, {
1176 | value: "511000",
1177 | text: "内江市"
1178 | }, {
1179 | value: "511100",
1180 | text: "乐山市"
1181 | }, {
1182 | value: "511300",
1183 | text: "南充市"
1184 | }, {
1185 | value: "511400",
1186 | text: "眉山市"
1187 | }, {
1188 | value: "511500",
1189 | text: "宜宾市"
1190 | }, {
1191 | value: "511600",
1192 | text: "广安市"
1193 | }, {
1194 | value: "511700",
1195 | text: "达州市"
1196 | }, {
1197 | value: "511800",
1198 | text: "雅安市"
1199 | }, {
1200 | value: "511900",
1201 | text: "巴中市"
1202 | }, {
1203 | value: "512000",
1204 | text: "资阳市"
1205 | }, {
1206 | value: "513200",
1207 | text: "阿坝藏族羌族自治州"
1208 | }, {
1209 | value: "513300",
1210 | text: "甘孜藏族自治州"
1211 | }, {
1212 | value: "513400",
1213 | text: "凉山彝族自治州"
1214 | }]
1215 | }, {
1216 | value: '520000',
1217 | text: '贵州省',
1218 | children: [{
1219 | value: "520100",
1220 | text: "贵阳市"
1221 | }, {
1222 | value: "520200",
1223 | text: "六盘水市"
1224 | }, {
1225 | value: "520300",
1226 | text: "遵义市"
1227 | }, {
1228 | value: "520400",
1229 | text: "安顺市"
1230 | }, {
1231 | value: "522200",
1232 | text: "铜仁地区"
1233 | }, {
1234 | value: "522300",
1235 | text: "黔西南布依族苗族自治州"
1236 | }, {
1237 | value: "522400",
1238 | text: "毕节地区"
1239 | }, {
1240 | value: "522600",
1241 | text: "黔东南苗族侗族自治州"
1242 | }, {
1243 | value: "522700",
1244 | text: "黔南布依族苗族自治州"
1245 | }]
1246 | }, {
1247 | value: '530000',
1248 | text: '云南省',
1249 | children: [{
1250 | value: "530100",
1251 | text: "昆明市"
1252 | }, {
1253 | value: "530300",
1254 | text: "曲靖市"
1255 | }, {
1256 | value: "530400",
1257 | text: "玉溪市"
1258 | }, {
1259 | value: "530500",
1260 | text: "保山市"
1261 | }, {
1262 | value: "530600",
1263 | text: "昭通市"
1264 | }, {
1265 | value: "530700",
1266 | text: "丽江市"
1267 | }, {
1268 | value: "530800",
1269 | text: "普洱市"
1270 | }, {
1271 | value: "530900",
1272 | text: "临沧市"
1273 | }, {
1274 | value: "532300",
1275 | text: "楚雄彝族自治州"
1276 | }, {
1277 | value: "532500",
1278 | text: "红河哈尼族彝族自治州"
1279 | }, {
1280 | value: "532600",
1281 | text: "文山壮族苗族自治州"
1282 | }, {
1283 | value: "532800",
1284 | text: "西双版纳傣族自治州"
1285 | }, {
1286 | value: "532900",
1287 | text: "大理白族自治州"
1288 | }, {
1289 | value: "533100",
1290 | text: "德宏傣族景颇族自治州"
1291 | }, {
1292 | value: "533300",
1293 | text: "怒江傈僳族自治州"
1294 | }, {
1295 | value: "533400",
1296 | text: "迪庆藏族自治州"
1297 | }]
1298 | }, {
1299 | value: '540000',
1300 | text: '西藏',
1301 | children: [{
1302 | value: "540100",
1303 | text: "拉萨市"
1304 | }, {
1305 | value: "542100",
1306 | text: "昌都地区"
1307 | }, {
1308 | value: "542200",
1309 | text: "山南地区"
1310 | }, {
1311 | value: "542300",
1312 | text: "日喀则地区"
1313 | }, {
1314 | value: "542400",
1315 | text: "那曲地区"
1316 | }, {
1317 | value: "542500",
1318 | text: "阿里地区"
1319 | }, {
1320 | value: "542600",
1321 | text: "林芝地区"
1322 | }]
1323 | }, {
1324 | value: '610000',
1325 | text: '陕西省',
1326 | children: [{
1327 | value: "610100",
1328 | text: "西安市"
1329 | }, {
1330 | value: "610200",
1331 | text: "铜川市"
1332 | }, {
1333 | value: "610300",
1334 | text: "宝鸡市"
1335 | }, {
1336 | value: "610400",
1337 | text: "咸阳市"
1338 | }, {
1339 | value: "610500",
1340 | text: "渭南市"
1341 | }, {
1342 | value: "610600",
1343 | text: "延安市"
1344 | }, {
1345 | value: "610700",
1346 | text: "汉中市"
1347 | }, {
1348 | value: "610800",
1349 | text: "榆林市"
1350 | }, {
1351 | value: "610900",
1352 | text: "安康市"
1353 | }, {
1354 | value: "611000",
1355 | text: "商洛市"
1356 | }]
1357 | }, {
1358 | value: '620000',
1359 | text: '甘肃省',
1360 | children: [{
1361 | value: "620100",
1362 | text: "兰州市"
1363 | }, {
1364 | value: "620200",
1365 | text: "嘉峪关市"
1366 | }, {
1367 | value: "620300",
1368 | text: "金昌市"
1369 | }, {
1370 | value: "620400",
1371 | text: "白银市"
1372 | }, {
1373 | value: "620500",
1374 | text: "天水市"
1375 | }, {
1376 | value: "620600",
1377 | text: "武威市"
1378 | }, {
1379 | value: "620700",
1380 | text: "张掖市"
1381 | }, {
1382 | value: "620800",
1383 | text: "平凉市"
1384 | }, {
1385 | value: "620900",
1386 | text: "酒泉市"
1387 | }, {
1388 | value: "621000",
1389 | text: "庆阳市"
1390 | }, {
1391 | value: "621100",
1392 | text: "定西市"
1393 | }, {
1394 | value: "621200",
1395 | text: "陇南市"
1396 | }, {
1397 | value: "622900",
1398 | text: "临夏回族自治州"
1399 | }, {
1400 | value: "623000",
1401 | text: "甘南藏族自治州"
1402 | }]
1403 | }, {
1404 | value: '630000',
1405 | text: '青海省',
1406 | children: [{
1407 | value: "630100",
1408 | text: "西宁市"
1409 | }, {
1410 | value: "632100",
1411 | text: "海东地区"
1412 | }, {
1413 | value: "632200",
1414 | text: "海北藏族自治州"
1415 | }, {
1416 | value: "632300",
1417 | text: "黄南藏族自治州"
1418 | }, {
1419 | value: "632500",
1420 | text: "海南藏族自治州"
1421 | }, {
1422 | value: "632600",
1423 | text: "果洛藏族自治州"
1424 | }, {
1425 | value: "632700",
1426 | text: "玉树藏族自治州"
1427 | }, {
1428 | value: "632800",
1429 | text: "海西蒙古族藏族自治州"
1430 | }]
1431 | }, {
1432 | value: '640000',
1433 | text: '宁夏',
1434 | children: [{
1435 | value: "640100",
1436 | text: "银川市"
1437 | }, {
1438 | value: "640200",
1439 | text: "石嘴山市"
1440 | }, {
1441 | value: "640300",
1442 | text: "吴忠市"
1443 | }, {
1444 | value: "640400",
1445 | text: "固原市"
1446 | }, {
1447 | value: "640500",
1448 | text: "中卫市"
1449 | }]
1450 | }, {
1451 | value: '650000',
1452 | text: '新疆',
1453 | children: [{
1454 | value: "650100",
1455 | text: "乌鲁木齐市"
1456 | }, {
1457 | value: "650200",
1458 | text: "克拉玛依市"
1459 | }, {
1460 | value: "652100",
1461 | text: "吐鲁番地区"
1462 | }, {
1463 | value: "652200",
1464 | text: "哈密地区"
1465 | }, {
1466 | value: "652300",
1467 | text: "昌吉回族自治州"
1468 | }, {
1469 | value: "652700",
1470 | text: "博尔塔拉蒙古自治州"
1471 | }, {
1472 | value: "652800",
1473 | text: "巴音郭楞蒙古自治州"
1474 | }, {
1475 | value: "652900",
1476 | text: "阿克苏地区"
1477 | }, {
1478 | value: "653000",
1479 | text: "克孜勒苏柯尔克孜自治州"
1480 | }, {
1481 | value: "653100",
1482 | text: "喀什地区"
1483 | }, {
1484 | value: "653200",
1485 | text: "和田地区"
1486 | }, {
1487 | value: "654000",
1488 | text: "伊犁哈萨克自治州"
1489 | }, {
1490 | value: "654200",
1491 | text: "塔城地区"
1492 | }, {
1493 | value: "654300",
1494 | text: "阿勒泰地区"
1495 | }, {
1496 | value: "659001",
1497 | text: "石河子市"
1498 | }, {
1499 | value: "659002",
1500 | text: "阿拉尔市"
1501 | }, {
1502 | value: "659003",
1503 | text: "图木舒克市"
1504 | }, {
1505 | value: "659004",
1506 | text: "五家渠市"
1507 | }]
1508 | }, {
1509 | value: '710000',
1510 | text: '台湾省',
1511 | children: [{
1512 | value: "710100",
1513 | text: "台北市"
1514 | }, {
1515 | value: "710200",
1516 | text: "高雄市"
1517 | }, {
1518 | value: "710300",
1519 | text: "台南市"
1520 | }, {
1521 | value: "710400",
1522 | text: "台中市"
1523 | }, {
1524 | value: "710500",
1525 | text: "金门县"
1526 | }, {
1527 | value: "710600",
1528 | text: "南投县"
1529 | }, {
1530 | value: "710700",
1531 | text: "基隆市"
1532 | }, {
1533 | value: "710800",
1534 | text: "新竹市"
1535 | }, {
1536 | value: "710900",
1537 | text: "嘉义市"
1538 | }, {
1539 | value: "711100",
1540 | text: "新北市"
1541 | }, {
1542 | value: "711200",
1543 | text: "宜兰县"
1544 | }, {
1545 | value: "711300",
1546 | text: "新竹县"
1547 | }, {
1548 | value: "711400",
1549 | text: "桃园县"
1550 | }, {
1551 | value: "711500",
1552 | text: "苗栗县"
1553 | }, {
1554 | value: "711700",
1555 | text: "彰化县"
1556 | }, {
1557 | value: "711900",
1558 | text: "嘉义县"
1559 | }, {
1560 | value: "712100",
1561 | text: "云林县"
1562 | }, {
1563 | value: "712400",
1564 | text: "屏东县"
1565 | }, {
1566 | value: "712500",
1567 | text: "台东县"
1568 | }, {
1569 | value: "712600",
1570 | text: "花莲县"
1571 | }, {
1572 | value: "712700",
1573 | text: "澎湖县"
1574 | }]
1575 | }, {
1576 | value: '810000',
1577 | text: '香港',
1578 | children: [{
1579 | value: "810100",
1580 | text: "香港岛"
1581 | }, {
1582 | value: "810200",
1583 | text: "九龙"
1584 | }, {
1585 | value: "810300",
1586 | text: "新界"
1587 | }]
1588 | }, {
1589 | value: '820000',
1590 | text: '澳门',
1591 | children: [{
1592 | value: "820100",
1593 | text: "澳门半岛"
1594 | }, {
1595 | value: "820200",
1596 | text: "离岛"
1597 | }]
1598 | }, {
1599 | value: '990000',
1600 | text: '海外',
1601 | children: [{
1602 | value: "990100",
1603 | text: "海外"
1604 | }]
1605 | }]
1606 |
--------------------------------------------------------------------------------
/src/js/mui.js:
--------------------------------------------------------------------------------
1 | var mui = (function(document, undefined) {
2 | var readyRE = /complete|loaded|interactive/;
3 | var idSelectorRE = /^#([\w-]+)$/;
4 | var classSelectorRE = /^\.([\w-]+)$/;
5 | var tagSelectorRE = /^[\w-]+$/;
6 | var translateRE = /translate(?:3d)?\((.+?)\)/;
7 | var translateMatrixRE = /matrix(3d)?\((.+?)\)/;
8 |
9 | var $ = function(selector, context) {
10 | context = context || document;
11 | if (!selector)
12 | return wrap();
13 | if (typeof selector === 'object')
14 | if ($.isArrayLike(selector)) {
15 | return wrap($.slice.call(selector), null);
16 | } else {
17 | return wrap([selector], null);
18 | }
19 | if (typeof selector === 'function')
20 | return $.ready(selector);
21 | if (typeof selector === 'string') {
22 | try {
23 | selector = selector.trim();
24 | if (idSelectorRE.test(selector)) {
25 | var found = document.getElementById(RegExp.$1);
26 | return wrap(found ? [found] : []);
27 | }
28 | return wrap($.qsa(selector, context), selector);
29 | } catch (e) {}
30 | }
31 | return wrap();
32 | };
33 |
34 | var wrap = function(dom, selector) {
35 | dom = dom || [];
36 | dom.__proto__ = $.fn;
37 | dom.selector = selector || '';
38 | return dom;
39 | };
40 |
41 | $.uuid = 0;
42 |
43 | $.data = {};
44 | /**
45 | * extend(simple)
46 | * @param {type} target
47 | * @param {type} source
48 | * @param {type} deep
49 | * @returns {unresolved}
50 | */
51 | $.extend = function() { //from jquery2
52 | var options, name, src, copy, copyIsArray, clone,
53 | target = arguments[0] || {},
54 | i = 1,
55 | length = arguments.length,
56 | deep = false;
57 |
58 | if (typeof target === "boolean") {
59 | deep = target;
60 |
61 | target = arguments[i] || {};
62 | i++;
63 | }
64 |
65 | if (typeof target !== "object" && !$.isFunction(target)) {
66 | target = {};
67 | }
68 |
69 | if (i === length) {
70 | target = this;
71 | i--;
72 | }
73 |
74 | for (; i < length; i++) {
75 | if ((options = arguments[i]) != null) {
76 | for (name in options) {
77 | src = target[name];
78 | copy = options[name];
79 |
80 | if (target === copy) {
81 | continue;
82 | }
83 |
84 | if (deep && copy && ($.isPlainObject(copy) || (copyIsArray = $.isArray(copy)))) {
85 | if (copyIsArray) {
86 | copyIsArray = false;
87 | clone = src && $.isArray(src) ? src : [];
88 |
89 | } else {
90 | clone = src && $.isPlainObject(src) ? src : {};
91 | }
92 |
93 | target[name] = $.extend(deep, clone, copy);
94 |
95 | } else if (copy !== undefined) {
96 | target[name] = copy;
97 | }
98 | }
99 | }
100 | }
101 |
102 | return target;
103 | };
104 | /**
105 | * mui noop(function)
106 | */
107 | $.noop = function() {};
108 | /**
109 | * mui slice(array)
110 | */
111 | $.slice = [].slice;
112 | /**
113 | * mui filter(array)
114 | */
115 | $.filter = [].filter;
116 |
117 | $.type = function(obj) {
118 | return obj == null ? String(obj) : class2type[{}.toString.call(obj)] || "object";
119 | };
120 | /**
121 | * mui isArray
122 | */
123 | $.isArray = Array.isArray ||
124 | function(object) {
125 | return object instanceof Array;
126 | };
127 | /**
128 | * mui isArrayLike
129 | * @param {Object} obj
130 | */
131 | $.isArrayLike = function(obj) {
132 | var length = !!obj && "length" in obj && obj.length;
133 | var type = $.type(obj);
134 | if (type === "function" || $.isWindow(obj)) {
135 | return false;
136 | }
137 | return type === "array" || length === 0 ||
138 | typeof length === "number" && length > 0 && (length - 1) in obj;
139 | };
140 | /**
141 | * mui isWindow(需考虑obj为undefined的情况)
142 | */
143 | $.isWindow = function(obj) {
144 | return obj != null && obj === obj.window;
145 | };
146 | /**
147 | * mui isObject
148 | */
149 | $.isObject = function(obj) {
150 | return $.type(obj) === "object";
151 | };
152 | /**
153 | * mui isPlainObject
154 | */
155 | $.isPlainObject = function(obj) {
156 | return $.isObject(obj) && !$.isWindow(obj) && Object.getPrototypeOf(obj) === Object.prototype;
157 | };
158 | /**
159 | * mui isEmptyObject
160 | * @param {Object} o
161 | */
162 | $.isEmptyObject = function(o) {
163 | for (var p in o) {
164 | if (p !== undefined) {
165 | return false;
166 | }
167 | }
168 | return true;
169 | };
170 | /**
171 | * mui isFunction
172 | */
173 | $.isFunction = function(value) {
174 | return $.type(value) === "function";
175 | };
176 | /**
177 | * mui querySelectorAll
178 | * @param {type} selector
179 | * @param {type} context
180 | * @returns {Array}
181 | */
182 | $.qsa = function(selector, context) {
183 | context = context || document;
184 | return $.slice.call(classSelectorRE.test(selector) ? context.getElementsByClassName(RegExp.$1) : tagSelectorRE.test(selector) ? context.getElementsByTagName(selector) : context.querySelectorAll(selector));
185 | };
186 | /**
187 | * ready(DOMContentLoaded)
188 | * @param {type} callback
189 | * @returns {_L6.$}
190 | */
191 | $.ready = function(callback) {
192 | if (readyRE.test(document.readyState)) {
193 | callback($);
194 | } else {
195 | document.addEventListener('DOMContentLoaded', function() {
196 | callback($);
197 | }, false);
198 | }
199 | return this;
200 | };
201 | /**
202 | * 将 fn 缓存一段时间后, 再被调用执行
203 | * 此方法为了避免在 ms 段时间内, 执行 fn 多次. 常用于 resize , scroll , mousemove 等连续性事件中;
204 | * 当 ms 设置为 -1, 表示立即执行 fn, 即和直接调用 fn 一样;
205 | * 调用返回函数的 stop 停止最后一次的 buffer 效果
206 | * @param {Object} fn
207 | * @param {Object} ms
208 | * @param {Object} context
209 | */
210 | $.buffer = function(fn, ms, context) {
211 | var timer;
212 | var lastStart = 0;
213 | var lastEnd = 0;
214 | var ms = ms || 150;
215 |
216 | function run() {
217 | if (timer) {
218 | timer.cancel();
219 | timer = 0;
220 | }
221 | lastStart = $.now();
222 | fn.apply(context || this, arguments);
223 | lastEnd = $.now();
224 | }
225 |
226 | return $.extend(function() {
227 | if (
228 | (!lastStart) || // 从未运行过
229 | (lastEnd >= lastStart && $.now() - lastEnd > ms) || // 上次运行成功后已经超过ms毫秒
230 | (lastEnd < lastStart && $.now() - lastStart > ms * 8) // 上次运行或未完成,后8*ms毫秒
231 | ) {
232 | run();
233 | } else {
234 | if (timer) {
235 | timer.cancel();
236 | }
237 | timer = $.later(run, ms, null, arguments);
238 | }
239 | }, {
240 | stop: function() {
241 | if (timer) {
242 | timer.cancel();
243 | timer = 0;
244 | }
245 | }
246 | });
247 | };
248 | /**
249 | * each
250 | * @param {type} elements
251 | * @param {type} callback
252 | * @returns {_L8.$}
253 | */
254 | $.each = function(elements, callback, hasOwnProperty) {
255 | if (!elements) {
256 | return this;
257 | }
258 | if (typeof elements.length === 'number') {
259 | [].every.call(elements, function(el, idx) {
260 | return callback.call(el, idx, el) !== false;
261 | });
262 | } else {
263 | for (var key in elements) {
264 | if (hasOwnProperty) {
265 | if (elements.hasOwnProperty(key)) {
266 | if (callback.call(elements[key], key, elements[key]) === false) return elements;
267 | }
268 | } else {
269 | if (callback.call(elements[key], key, elements[key]) === false) return elements;
270 | }
271 | }
272 | }
273 | return this;
274 | };
275 | $.focus = function(element) {
276 | if ($.os.ios) {
277 | setTimeout(function() {
278 | element.focus();
279 | }, 10);
280 | } else {
281 | element.focus();
282 | }
283 | };
284 | /**
285 | * trigger event
286 | * @param {type} element
287 | * @param {type} eventType
288 | * @param {type} eventData
289 | * @returns {_L8.$}
290 | */
291 | $.trigger = function(element, eventType, eventData) {
292 | element.dispatchEvent(new CustomEvent(eventType, {
293 | detail: eventData,
294 | bubbles: true,
295 | cancelable: true
296 | }));
297 | return this;
298 | };
299 | /**
300 | * getStyles
301 | * @param {type} element
302 | * @param {type} property
303 | * @returns {styles}
304 | */
305 | $.getStyles = function(element, property) {
306 | var styles = element.ownerDocument.defaultView.getComputedStyle(element, null);
307 | if (property) {
308 | return styles.getPropertyValue(property) || styles[property];
309 | }
310 | return styles;
311 | };
312 | /**
313 | * parseTranslate
314 | * @param {type} translateString
315 | * @param {type} position
316 | * @returns {Object}
317 | */
318 | $.parseTranslate = function(translateString, position) {
319 | var result = translateString.match(translateRE || '');
320 | if (!result || !result[1]) {
321 | result = ['', '0,0,0'];
322 | }
323 | result = result[1].split(",");
324 | result = {
325 | x: parseFloat(result[0]),
326 | y: parseFloat(result[1]),
327 | z: parseFloat(result[2])
328 | };
329 | if (position && result.hasOwnProperty(position)) {
330 | return result[position];
331 | }
332 | return result;
333 | };
334 | /**
335 | * parseTranslateMatrix
336 | * @param {type} translateString
337 | * @param {type} position
338 | * @returns {Object}
339 | */
340 | $.parseTranslateMatrix = function(translateString, position) {
341 | var matrix = translateString.match(translateMatrixRE);
342 | var is3D = matrix && matrix[1];
343 | if (matrix) {
344 | matrix = matrix[2].split(",");
345 | if (is3D === "3d")
346 | matrix = matrix.slice(12, 15);
347 | else {
348 | matrix.push(0);
349 | matrix = matrix.slice(4, 7);
350 | }
351 | } else {
352 | matrix = [0, 0, 0];
353 | }
354 | var result = {
355 | x: parseFloat(matrix[0]),
356 | y: parseFloat(matrix[1]),
357 | z: parseFloat(matrix[2])
358 | };
359 | if (position && result.hasOwnProperty(position)) {
360 | return result[position];
361 | }
362 | return result;
363 | };
364 | $.hooks = {};
365 | $.addAction = function(type, hook) {
366 | var hooks = $.hooks[type];
367 | if (!hooks) {
368 | hooks = [];
369 | }
370 | hook.index = hook.index || 1000;
371 | hooks.push(hook);
372 | hooks.sort(function(a, b) {
373 | return a.index - b.index;
374 | });
375 | $.hooks[type] = hooks;
376 | return $.hooks[type];
377 | };
378 | $.doAction = function(type, callback) {
379 | if ($.isFunction(callback)) { //指定了callback
380 | $.each($.hooks[type], callback);
381 | } else { //未指定callback,直接执行
382 | $.each($.hooks[type], function(index, hook) {
383 | return !hook.handle();
384 | });
385 | }
386 | };
387 | /**
388 | * setTimeout封装
389 | * @param {Object} fn
390 | * @param {Object} when
391 | * @param {Object} context
392 | * @param {Object} data
393 | */
394 | $.later = function(fn, when, context, data) {
395 | when = when || 0;
396 | var m = fn;
397 | var d = data;
398 | var f;
399 | var r;
400 |
401 | if (typeof fn === 'string') {
402 | m = context[fn];
403 | }
404 |
405 | f = function() {
406 | m.apply(context, $.isArray(d) ? d : [d]);
407 | };
408 |
409 | r = setTimeout(f, when);
410 |
411 | return {
412 | id: r,
413 | cancel: function() {
414 | clearTimeout(r);
415 | }
416 | };
417 | };
418 | $.now = Date.now || function() {
419 | return +new Date();
420 | };
421 | var class2type = {};
422 | $.each(['Boolean', 'Number', 'String', 'Function', 'Array', 'Date', 'RegExp', 'Object', 'Error'], function(i, name) {
423 | class2type["[object " + name + "]"] = name.toLowerCase();
424 | });
425 | if (window.JSON) {
426 | $.parseJSON = JSON.parse;
427 | }
428 | /**
429 | * $.fn
430 | */
431 | $.fn = {
432 | each: function(callback) {
433 | [].every.call(this, function(el, idx) {
434 | return callback.call(el, idx, el) !== false;
435 | });
436 | return this;
437 | }
438 | };
439 |
440 | return $;
441 | })(document);
442 |
443 |
444 |
445 | (function($, window) {
446 | function detect(ua) {
447 | this.os = {};
448 | var funcs = [
449 |
450 | function() { //wechat
451 | var wechat = ua.match(/(MicroMessenger)\/([\d\.]+)/i);
452 | if (wechat) { //wechat
453 | this.os.wechat = {
454 | version: wechat[2].replace(/_/g, '.')
455 | };
456 | }
457 | return false;
458 | },
459 | function() { //android
460 | var android = ua.match(/(Android);?[\s\/]+([\d.]+)?/);
461 | if (android) {
462 | this.os.android = true;
463 | this.os.version = android[2];
464 |
465 | this.os.isBadAndroid = !(/Chrome\/\d/.test(window.navigator.appVersion));
466 | }
467 | return this.os.android === true;
468 | },
469 | function() { //ios
470 | var iphone = ua.match(/(iPhone\sOS)\s([\d_]+)/);
471 | if (iphone) { //iphone
472 | this.os.ios = this.os.iphone = true;
473 | this.os.version = iphone[2].replace(/_/g, '.');
474 | } else {
475 | var ipad = ua.match(/(iPad).*OS\s([\d_]+)/);
476 | if (ipad) { //ipad
477 | this.os.ios = this.os.ipad = true;
478 | this.os.version = ipad[2].replace(/_/g, '.');
479 | }
480 | }
481 | return this.os.ios === true;
482 | }
483 | ];
484 | [].every.call(funcs, function(func) {
485 | return !func.call($);
486 | });
487 | }
488 | detect.call($, navigator.userAgent);
489 | })(mui, window);
490 | /**
491 | * $.os.plus
492 | * @param {type} $
493 | * @returns {undefined}
494 | */
495 | (function($, document) {
496 | function detect(ua) {
497 | this.os = this.os || {};
498 | var plus = ua.match(/Html5Plus/i); //TODO 5\+Browser?
499 | if (plus) {
500 | this.os.plus = true;
501 | $(function() {
502 | document.body.classList.add('mui-plus');
503 | });
504 | if (ua.match(/StreamApp/i)) { //TODO 最好有流应用自己的标识
505 | this.os.stream = true;
506 | $(function() {
507 | document.body.classList.add('mui-plus-stream');
508 | });
509 | }
510 | }
511 | }
512 | detect.call($, navigator.userAgent);
513 | })(mui, document);
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 | (function($) {
526 | var initializing = false,
527 | fnTest = /xyz/.test(function() {
528 | xyz;
529 | }) ? /\b_super\b/ : /.*/;
530 |
531 | var Class = function() {};
532 | Class.extend = function(prop) {
533 | var _super = this.prototype;
534 | initializing = true;
535 | var prototype = new this();
536 | initializing = false;
537 | for (var name in prop) {
538 | prototype[name] = typeof prop[name] == "function" &&
539 | typeof _super[name] == "function" && fnTest.test(prop[name]) ?
540 | (function(name, fn) {
541 | return function() {
542 | var tmp = this._super;
543 |
544 | this._super = _super[name];
545 |
546 | var ret = fn.apply(this, arguments);
547 | this._super = tmp;
548 |
549 | return ret;
550 | };
551 | })(name, prop[name]) :
552 | prop[name];
553 | }
554 | function Class() {
555 | if (!initializing && this.init)
556 | this.init.apply(this, arguments);
557 | }
558 | Class.prototype = prototype;
559 | Class.prototype.constructor = Class;
560 | Class.extend = this;
561 | return Class;
562 | };
563 | $.Class = Class;
564 | })(mui);
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 | /**
579 | * mui.init
580 | * @param {type} $
581 | * @returns {undefined}
582 | */
583 | (function($) {
584 | $.global = $.options = {
585 | gestureConfig: {
586 | tap: true,
587 | doubletap: false,
588 | longtap: false,
589 | hold: false,
590 | flick: true,
591 | swipe: true,
592 | drag: true,
593 | pinch: false
594 | }
595 | };
596 | /**
597 | *
598 | * @param {type} options
599 | * @returns {undefined}
600 | */
601 | $.initGlobal = function(options) {
602 | $.options = $.extend(true, $.global, options);
603 | return this;
604 | };
605 | var inits = {};
606 |
607 | var isInitialized = false;
608 | //TODO 自动调用init?因为用户自己调用init的时机可能不确定,如果晚于自动init,则会有潜在问题
609 | // $.ready(function() {
610 | // setTimeout(function() {
611 | // if (!isInitialized) {
612 | // $.init();
613 | // }
614 | // }, 300);
615 | // });
616 | /**
617 | * 单页配置 初始化
618 | * @param {object} options
619 | */
620 | $.init = function(options) {
621 | isInitialized = true;
622 | $.options = $.extend(true, $.global, options || {});
623 | $.ready(function() {
624 | $.doAction('inits', function(index, init) {
625 | var isInit = !!(!inits[init.name] || init.repeat);
626 | if (isInit) {
627 | init.handle.call($);
628 | inits[init.name] = true;
629 | }
630 | });
631 | });
632 | return this;
633 | };
634 |
635 | /**
636 | * 增加初始化执行流程
637 | * @param {function} init
638 | */
639 | $.addInit = function(init) {
640 | return $.addAction('inits', init);
641 | };
642 |
643 |
644 | })(mui);
645 |
646 |
647 |
648 |
649 |
650 | /**
651 | * mui target(action>popover>modal>tab>toggle)
652 | */
653 | (function($, window, document) {
654 | /**
655 | * targets
656 | */
657 | $.targets = {};
658 | /**
659 | * target handles
660 | */
661 | $.targetHandles = [];
662 | /**
663 | * register target
664 | * @param {type} target
665 | * @returns {$.targets}
666 | */
667 | $.registerTarget = function(target) {
668 |
669 | target.index = target.index || 1000;
670 |
671 | $.targetHandles.push(target);
672 |
673 | $.targetHandles.sort(function(a, b) {
674 | return a.index - b.index;
675 | });
676 |
677 | return $.targetHandles;
678 | };
679 | window.addEventListener($.EVENT_START, function(event) {
680 | var target = event.target;
681 | var founds = {};
682 | for (; target && target !== document; target = target.parentNode) {
683 | var isFound = false;
684 | $.each($.targetHandles, function(index, targetHandle) {
685 | var name = targetHandle.name;
686 | if (!isFound && !founds[name] && targetHandle.hasOwnProperty('handle')) {
687 | $.targets[name] = targetHandle.handle(event, target);
688 | if ($.targets[name]) {
689 | founds[name] = true;
690 | if (targetHandle.isContinue !== true) {
691 | isFound = true;
692 | }
693 | }
694 | } else {
695 | if (!founds[name]) {
696 | if (targetHandle.isReset !== false)
697 | $.targets[name] = false;
698 | }
699 | }
700 | });
701 | if (isFound) {
702 | break;
703 | }
704 | }
705 | });
706 | window.addEventListener('click', function(event) { //解决touch与click的target不一致的问题(比如链接边缘点击时,touch的target为html,而click的target为A)
707 | var target = event.target;
708 | var isFound = false;
709 | for (; target && target !== document; target = target.parentNode) {
710 | if (target.tagName === 'A') {
711 | $.each($.targetHandles, function(index, targetHandle) {
712 | var name = targetHandle.name;
713 | if (targetHandle.hasOwnProperty('handle')) {
714 | if (targetHandle.handle(event, target)) {
715 | isFound = true;
716 | event.preventDefault();
717 | return false;
718 | }
719 | }
720 | });
721 | if (isFound) {
722 | break;
723 | }
724 | }
725 | }
726 | });
727 | })(mui, window, document);
728 |
729 |
730 |
731 |
732 |
733 |
734 |
735 | /**
736 | * Popovers
737 | * @param {type} $
738 | * @param {type} window
739 | * @param {type} document
740 | * @param {type} name
741 | * @param {type} undefined
742 | * @returns {undefined}
743 | */
744 | (function($, window, document, name) {
745 |
746 | var CLASS_POPOVER = 'mui-popover';
747 | var CLASS_POPOVER_ARROW = 'mui-popover-arrow';
748 | var CLASS_ACTION_POPOVER = 'mui-popover-action';
749 | var CLASS_BACKDROP = 'mui-backdrop';
750 | var CLASS_BAR_POPOVER = 'mui-bar-popover';
751 | var CLASS_BAR_BACKDROP = 'mui-bar-backdrop';
752 | var CLASS_ACTION_BACKDROP = 'mui-backdrop-action';
753 | var CLASS_ACTIVE = 'mui-active';
754 | var CLASS_BOTTOM = 'mui-bottom';
755 |
756 |
757 |
758 | var handle = function(event, target) {
759 | if (target.tagName === 'A' && target.hash) {
760 | $.targets._popover = document.getElementById(target.hash.replace('#', ''));
761 | if ($.targets._popover && $.targets._popover.classList.contains(CLASS_POPOVER)) {
762 | return target;
763 | } else {
764 | $.targets._popover = null;
765 | }
766 | }
767 | return false;
768 | };
769 |
770 | $.registerTarget({
771 | name: name,
772 | index: 60,
773 | handle: handle,
774 | target: false,
775 | isReset: false,
776 | isContinue: true
777 | });
778 |
779 | var fixedPopoverScroll = function(isPopoverScroll) {
780 | // if (isPopoverScroll) {
781 | // document.body.setAttribute('style', 'overflow:hidden;');
782 | // } else {
783 | // document.body.setAttribute('style', '');
784 | // }
785 | };
786 | var onPopoverShown = function(e) {
787 | this.removeEventListener('webkitTransitionEnd', onPopoverShown);
788 | this.addEventListener($.EVENT_MOVE, $.preventDefault);
789 | $.trigger(this, 'shown', this);
790 | }
791 | var onPopoverHidden = function(e) {
792 | setStyle(this, 'none');
793 | this.removeEventListener('webkitTransitionEnd', onPopoverHidden);
794 | this.removeEventListener($.EVENT_MOVE, $.preventDefault);
795 | fixedPopoverScroll(false);
796 | $.trigger(this, 'hidden', this);
797 | };
798 |
799 | var backdrop = (function() {
800 | var element = document.createElement('div');
801 | element.classList.add(CLASS_BACKDROP);
802 | element.addEventListener($.EVENT_MOVE, $.preventDefault);
803 | element.addEventListener('tap', function(e) {
804 | var popover = $.targets._popover;
805 | if (popover) {
806 | popover.addEventListener('webkitTransitionEnd', onPopoverHidden);
807 | popover.classList.remove(CLASS_ACTIVE);
808 | removeBackdrop(popover);
809 | document.body.setAttribute('style', ''); //webkitTransitionEnd有时候不触发?
810 | }
811 | });
812 |
813 | return element;
814 | }());
815 | var removeBackdropTimer;
816 | var removeBackdrop = function(popover) {
817 | backdrop.setAttribute('style', 'opacity:0');
818 | $.targets.popover = $.targets._popover = null; //reset
819 | removeBackdropTimer = $.later(function() {
820 | if (!popover.classList.contains(CLASS_ACTIVE) && backdrop.parentNode && backdrop.parentNode === document.body) {
821 | document.body.removeChild(backdrop);
822 | }
823 | }, 350);
824 | };
825 | window.addEventListener('tap', function(e) {
826 | if (!$.targets.popover) {
827 | return;
828 | }
829 | var toggle = false;
830 | var target = e.target;
831 | for (; target && target !== document; target = target.parentNode) {
832 | if (target === $.targets.popover) {
833 | toggle = true;
834 | }
835 | }
836 | if (toggle) {
837 | e.detail.gesture.preventDefault(); //fixed hashchange
838 | togglePopover($.targets._popover, $.targets.popover);
839 | }
840 |
841 | });
842 |
843 | var togglePopover = function(popover, anchor, state) {
844 | if ((state === 'show' && popover.classList.contains(CLASS_ACTIVE)) || (state === 'hide' && !popover.classList.contains(CLASS_ACTIVE))) {
845 | return;
846 | }
847 | removeBackdropTimer && removeBackdropTimer.cancel(); //取消remove的timer
848 | //remove一遍,以免来回快速切换,导致webkitTransitionEnd不触发,无法remove
849 | popover.removeEventListener('webkitTransitionEnd', onPopoverShown);
850 | popover.removeEventListener('webkitTransitionEnd', onPopoverHidden);
851 | backdrop.classList.remove(CLASS_BAR_BACKDROP);
852 | backdrop.classList.remove(CLASS_ACTION_BACKDROP);
853 | var _popover = document.querySelector('.mui-popover.mui-active');
854 | if (_popover) {
855 | // _popover.setAttribute('style', '');
856 | _popover.addEventListener('webkitTransitionEnd', onPopoverHidden);
857 | _popover.classList.remove(CLASS_ACTIVE);
858 | // _popover.removeEventListener('webkitTransitionEnd', onPopoverHidden);
859 | // fixedPopoverScroll(false);
860 | //同一个弹出则直接返回,解决同一个popover的toggle
861 | if (popover === _popover) {
862 | removeBackdrop(_popover);
863 | return;
864 | }
865 | }
866 | var isActionSheet = false;
867 | if (popover.classList.contains(CLASS_BAR_POPOVER) || popover.classList.contains(CLASS_ACTION_POPOVER)) { //navBar
868 | if (popover.classList.contains(CLASS_ACTION_POPOVER)) { //action sheet popover
869 | isActionSheet = true;
870 | backdrop.classList.add(CLASS_ACTION_BACKDROP);
871 | } else { //bar popover
872 | backdrop.classList.add(CLASS_BAR_BACKDROP);
873 | // if (anchor) {
874 | // if (anchor.parentNode) {
875 | // var offsetWidth = anchor.offsetWidth;
876 | // var offsetLeft = anchor.offsetLeft;
877 | // var innerWidth = window.innerWidth;
878 | // popover.style.left = (Math.min(Math.max(offsetLeft, defaultPadding), innerWidth - offsetWidth - defaultPadding)) + "px";
879 | // } else {
880 | // //TODO anchor is position:{left,top,bottom,right}
881 | // }
882 | // }
883 | }
884 | }
885 | setStyle(popover, 'block'); //actionsheet transform
886 | popover.offsetHeight;
887 | popover.classList.add(CLASS_ACTIVE);
888 | backdrop.setAttribute('style', '');
889 | document.body.appendChild(backdrop);
890 | fixedPopoverScroll(true);
891 | calPosition(popover, anchor, isActionSheet); //position
892 | backdrop.classList.add(CLASS_ACTIVE);
893 | popover.addEventListener('webkitTransitionEnd', onPopoverShown);
894 | };
895 | var setStyle = function(popover, display, top, left) {
896 | var style = popover.style;
897 | if (typeof display !== 'undefined')
898 | style.display = display;
899 | if (typeof top !== 'undefined')
900 | style.top = top + 'px';
901 | if (typeof left !== 'undefined')
902 | style.left = left + 'px';
903 | };
904 | var calPosition = function(popover, anchor, isActionSheet) {
905 | if (!popover || !anchor) {
906 | return;
907 | }
908 |
909 | if (isActionSheet) { //actionsheet
910 | setStyle(popover, 'block')
911 | return;
912 | }
913 |
914 | var wWidth = window.innerWidth;
915 | var wHeight = window.innerHeight;
916 |
917 | var pWidth = popover.offsetWidth;
918 | var pHeight = popover.offsetHeight;
919 |
920 | var aWidth = anchor.offsetWidth;
921 | var aHeight = anchor.offsetHeight;
922 | var offset = $.offset(anchor);
923 |
924 | var arrow = popover.querySelector('.' + CLASS_POPOVER_ARROW);
925 | if (!arrow) {
926 | arrow = document.createElement('div');
927 | arrow.className = CLASS_POPOVER_ARROW;
928 | popover.appendChild(arrow);
929 | }
930 | var arrowSize = arrow && arrow.offsetWidth / 2 || 0;
931 |
932 |
933 |
934 | var pTop = 0;
935 | var pLeft = 0;
936 | var diff = 0;
937 | var arrowLeft = 0;
938 | var defaultPadding = popover.classList.contains(CLASS_ACTION_POPOVER) ? 0 : 5;
939 |
940 | var position = 'top';
941 | if ((pHeight + arrowSize) < (offset.top - window.pageYOffset)) { //top
942 | pTop = offset.top - pHeight - arrowSize;
943 | } else if ((pHeight + arrowSize) < (wHeight - (offset.top - window.pageYOffset) - aHeight)) { //bottom
944 | position = 'bottom';
945 | pTop = offset.top + aHeight + arrowSize;
946 | } else { //middle
947 | position = 'middle';
948 | pTop = Math.max((wHeight - pHeight) / 2 + window.pageYOffset, 0);
949 | pLeft = Math.max((wWidth - pWidth) / 2 + window.pageXOffset, 0);
950 | }
951 | if (position === 'top' || position === 'bottom') {
952 | pLeft = aWidth / 2 + offset.left - pWidth / 2;
953 | diff = pLeft;
954 | if (pLeft < defaultPadding) pLeft = defaultPadding;
955 | if (pLeft + pWidth > wWidth) pLeft = wWidth - pWidth - defaultPadding;
956 |
957 | if (arrow) {
958 | if (position === 'top') {
959 | arrow.classList.add(CLASS_BOTTOM);
960 | } else {
961 | arrow.classList.remove(CLASS_BOTTOM);
962 | }
963 | diff = diff - pLeft;
964 | arrowLeft = (pWidth / 2 - arrowSize / 2 + diff);
965 | arrowLeft = Math.max(Math.min(arrowLeft, pWidth - arrowSize * 2 - 6), 6);
966 | arrow.setAttribute('style', 'left:' + arrowLeft + 'px');
967 | }
968 | } else if (position === 'middle') {
969 | arrow.setAttribute('style', 'display:none');
970 | }
971 | setStyle(popover, 'block', pTop, pLeft);
972 | };
973 |
974 | $.createMask = function(callback) {
975 | var element = document.createElement('div');
976 | element.classList.add(CLASS_BACKDROP);
977 | element.addEventListener($.EVENT_MOVE, $.preventDefault);
978 | element.addEventListener('tap', function() {
979 | mask.close();
980 | });
981 | var mask = [element];
982 | mask._show = false;
983 | mask.show = function() {
984 | mask._show = true;
985 | element.setAttribute('style', 'opacity:1');
986 | document.body.appendChild(element);
987 | return mask;
988 | };
989 | mask._remove = function() {
990 | if (mask._show) {
991 | mask._show = false;
992 | element.setAttribute('style', 'opacity:0');
993 | $.later(function() {
994 | var body = document.body;
995 | element.parentNode === body && body.removeChild(element);
996 | }, 350);
997 | }
998 | return mask;
999 | };
1000 | mask.close = function() {
1001 | if (callback) {
1002 | if (callback() !== false) {
1003 | mask._remove();
1004 | }
1005 | } else {
1006 | mask._remove();
1007 | }
1008 | };
1009 | return mask;
1010 | };
1011 | $.fn.popover = function() {
1012 | var args = arguments;
1013 | this.each(function() {
1014 | $.targets._popover = this;
1015 | if (args[0] === 'show' || args[0] === 'hide' || args[0] === 'toggle') {
1016 | togglePopover(this, args[1], args[0]);
1017 | }
1018 | });
1019 | };
1020 |
1021 | })(mui, window, document, 'popover');
1022 |
1023 |
1024 |
1025 | /**
1026 | * mui namespace(optimization)
1027 | * @param {type} $
1028 | * @returns {undefined}
1029 | */
1030 | (function($) {
1031 | $.namespace = 'mui';
1032 | $.classNamePrefix = $.namespace + '-';
1033 | $.classSelectorPrefix = '.' + $.classNamePrefix;
1034 | /**
1035 | * 返回正确的className
1036 | * @param {type} className
1037 | * @returns {String}
1038 | */
1039 | $.className = function(className) {
1040 | return $.classNamePrefix + className;
1041 | };
1042 | /**
1043 | * 返回正确的classSelector
1044 | * @param {type} classSelector
1045 | * @returns {String}
1046 | */
1047 | $.classSelector = function(classSelector) {
1048 | return classSelector.replace(/\./g, $.classSelectorPrefix);
1049 | };
1050 | /**
1051 | * 返回正确的eventName
1052 | * @param {type} event
1053 | * @param {type} module
1054 | * @returns {String}
1055 | */
1056 | $.eventName = function(event, module) {
1057 | return event + ($.namespace ? ('.' + $.namespace) : '') + ( module ? ('.' + module) : '');
1058 | };
1059 | })(mui);
1060 |
1061 |
1062 |
1063 |
1064 |
1065 |
1066 |
1067 |
1068 |
1069 |
1070 |
1071 |
1072 |
1073 |
1074 |
1075 | /**
1076 | * 仅提供简单的on,off(仅支持事件委托,不支持当前元素绑定,当前元素绑定请直接使用addEventListener,removeEventListener)
1077 | * @param {Object} $
1078 | */
1079 | (function($) {
1080 | if ('ontouchstart' in window) {
1081 | $.isTouchable = true;
1082 | $.EVENT_START = 'touchstart';
1083 | $.EVENT_MOVE = 'touchmove';
1084 | $.EVENT_END = 'touchend';
1085 | } else {
1086 | $.isTouchable = false;
1087 | $.EVENT_START = 'mousedown';
1088 | $.EVENT_MOVE = 'mousemove';
1089 | $.EVENT_END = 'mouseup';
1090 | }
1091 | $.EVENT_CANCEL = 'touchcancel';
1092 | $.EVENT_CLICK = 'click';
1093 |
1094 | var _mid = 1;
1095 | var delegates = {};
1096 | //需要wrap的函数
1097 | var eventMethods = {
1098 | preventDefault: 'isDefaultPrevented',
1099 | stopImmediatePropagation: 'isImmediatePropagationStopped',
1100 | stopPropagation: 'isPropagationStopped'
1101 | };
1102 | //默认true返回函数
1103 | var returnTrue = function() {
1104 | return true
1105 | };
1106 | //默认false返回函数
1107 | var returnFalse = function() {
1108 | return false
1109 | };
1110 | //wrap浏览器事件
1111 | var compatible = function(event, target) {
1112 | if (!event.detail) {
1113 | event.detail = {
1114 | currentTarget: target
1115 | };
1116 | } else {
1117 | event.detail.currentTarget = target;
1118 | }
1119 | $.each(eventMethods, function(name, predicate) {
1120 | var sourceMethod = event[name];
1121 | event[name] = function() {
1122 | this[predicate] = returnTrue;
1123 | return sourceMethod && sourceMethod.apply(event, arguments)
1124 | }
1125 | event[predicate] = returnFalse;
1126 | }, true);
1127 | return event;
1128 | };
1129 | //简单的wrap对象_mid
1130 | var mid = function(obj) {
1131 | return obj && (obj._mid || (obj._mid = _mid++));
1132 | };
1133 | //事件委托对象绑定的事件回调列表
1134 | var delegateFns = {};
1135 | //返回事件委托的wrap事件回调
1136 | var delegateFn = function(element, event, selector, callback) {
1137 | return function(e) {
1138 | //same event
1139 | var callbackObjs = delegates[element._mid][event];
1140 | var handlerQueue = [];
1141 | var target = e.target;
1142 | var selectorAlls = {};
1143 | for (; target && target !== document; target = target.parentNode) {
1144 | if (target === element) {
1145 | break;
1146 | }
1147 | if (~['click', 'tap', 'doubletap', 'longtap', 'hold'].indexOf(event) && (target.disabled || target.classList.contains($.className('disabled')))) {
1148 | break;
1149 | }
1150 | var matches = {};
1151 | $.each(callbackObjs, function(selector, callbacks) { //same selector
1152 | selectorAlls[selector] || (selectorAlls[selector] = $.qsa(selector, element));
1153 | if (selectorAlls[selector] && ~(selectorAlls[selector]).indexOf(target)) {
1154 | if (!matches[selector]) {
1155 | matches[selector] = callbacks;
1156 | }
1157 | }
1158 | }, true);
1159 | if (!$.isEmptyObject(matches)) {
1160 | handlerQueue.push({
1161 | element: target,
1162 | handlers: matches
1163 | });
1164 | }
1165 | }
1166 | selectorAlls = null;
1167 | e = compatible(e); //compatible event
1168 | $.each(handlerQueue, function(index, handler) {
1169 | target = handler.element;
1170 | var tagName = target.tagName;
1171 | if (event === 'tap' && (tagName !== 'INPUT' && tagName !== 'TEXTAREA' && tagName !== 'SELECT')) {
1172 | e.preventDefault();
1173 | e.detail && e.detail.gesture && e.detail.gesture.preventDefault();
1174 | }
1175 | $.each(handler.handlers, function(index, handler) {
1176 | $.each(handler, function(index, callback) {
1177 | if (callback.call(target, e) === false) {
1178 | e.preventDefault();
1179 | e.stopPropagation();
1180 | }
1181 | }, true);
1182 | }, true)
1183 | if (e.isPropagationStopped()) {
1184 | return false;
1185 | }
1186 | }, true);
1187 | };
1188 | };
1189 | var findDelegateFn = function(element, event) {
1190 | var delegateCallbacks = delegateFns[mid(element)];
1191 | var result = [];
1192 | if (delegateCallbacks) {
1193 | result = [];
1194 | if (event) {
1195 | var filterFn = function(fn) {
1196 | return fn.type === event;
1197 | }
1198 | return delegateCallbacks.filter(filterFn);
1199 | } else {
1200 | result = delegateCallbacks;
1201 | }
1202 | }
1203 | return result;
1204 | };
1205 | var preventDefaultException = /^(INPUT|TEXTAREA|BUTTON|SELECT)$/;
1206 | /**
1207 | * mui delegate events
1208 | * @param {type} event
1209 | * @param {type} selector
1210 | * @param {type} callback
1211 | * @returns {undefined}
1212 | */
1213 | $.fn.on = function(event, selector, callback) { //仅支持简单的事件委托,主要是tap事件使用,类似mouse,focus之类暂不封装支持
1214 | return this.each(function() {
1215 | var element = this;
1216 | mid(element);
1217 | mid(callback);
1218 | var isAddEventListener = false;
1219 | var delegateEvents = delegates[element._mid] || (delegates[element._mid] = {});
1220 | var delegateCallbackObjs = delegateEvents[event] || ((delegateEvents[event] = {}));
1221 | if ($.isEmptyObject(delegateCallbackObjs)) {
1222 | isAddEventListener = true;
1223 | }
1224 | var delegateCallbacks = delegateCallbackObjs[selector] || (delegateCallbackObjs[selector] = []);
1225 | delegateCallbacks.push(callback);
1226 | if (isAddEventListener) {
1227 | var delegateFnArray = delegateFns[mid(element)];
1228 | if (!delegateFnArray) {
1229 | delegateFnArray = [];
1230 | }
1231 | var delegateCallback = delegateFn(element, event, selector, callback);
1232 | delegateFnArray.push(delegateCallback);
1233 | delegateCallback.i = delegateFnArray.length - 1;
1234 | delegateCallback.type = event;
1235 | delegateFns[mid(element)] = delegateFnArray;
1236 | element.addEventListener(event, delegateCallback);
1237 | if (event === 'tap') { //TODO 需要找个更好的解决方案
1238 | element.addEventListener('click', function(e) {
1239 | if (e.target) {
1240 | var tagName = e.target.tagName;
1241 | if (!preventDefaultException.test(tagName)) {
1242 | if (tagName === 'A') {
1243 | var href = e.target.href;
1244 | if (!(href && ~href.indexOf('tel:'))) {
1245 | e.preventDefault();
1246 | }
1247 | } else {
1248 | e.preventDefault();
1249 | }
1250 | }
1251 | }
1252 | });
1253 | }
1254 | }
1255 | });
1256 | };
1257 | $.fn.off = function(event, selector, callback) {
1258 | return this.each(function() {
1259 | var _mid = mid(this);
1260 | if (!event) { //mui(selector).off();
1261 | delegates[_mid] && delete delegates[_mid];
1262 | } else if (!selector) { //mui(selector).off(event);
1263 | delegates[_mid] && delete delegates[_mid][event];
1264 | } else if (!callback) { //mui(selector).off(event,selector);
1265 | delegates[_mid] && delegates[_mid][event] && delete delegates[_mid][event][selector];
1266 | } else { //mui(selector).off(event,selector,callback);
1267 | var delegateCallbacks = delegates[_mid] && delegates[_mid][event] && delegates[_mid][event][selector];
1268 | $.each(delegateCallbacks, function(index, delegateCallback) {
1269 | if (mid(delegateCallback) === mid(callback)) {
1270 | delegateCallbacks.splice(index, 1);
1271 | return false;
1272 | }
1273 | }, true);
1274 | }
1275 | if (delegates[_mid]) {
1276 | //如果off掉了所有当前element的指定的event事件,则remove掉当前element的delegate回调
1277 | if ((!delegates[_mid][event] || $.isEmptyObject(delegates[_mid][event]))) {
1278 | findDelegateFn(this, event).forEach(function(fn) {
1279 | this.removeEventListener(fn.type, fn);
1280 | delete delegateFns[_mid][fn.i];
1281 | }.bind(this));
1282 | }
1283 | } else {
1284 | //如果delegates[_mid]已不存在,删除所有
1285 | findDelegateFn(this).forEach(function(fn) {
1286 | this.removeEventListener(fn.type, fn);
1287 | delete delegateFns[_mid][fn.i];
1288 | }.bind(this));
1289 | }
1290 | });
1291 |
1292 | };
1293 | })(mui);
1294 |
1295 |
1296 |
1297 |
1298 | /**
1299 | * mui gestures
1300 | * @param {type} $
1301 | * @param {type} window
1302 | * @returns {undefined}
1303 | */
1304 | (function($, window) {
1305 | $.gestures = {
1306 | session: {}
1307 | };
1308 | /**
1309 | * Gesture preventDefault
1310 | * @param {type} e
1311 | * @returns {undefined}
1312 | */
1313 | $.preventDefault = function(e) {
1314 | e.preventDefault();
1315 | };
1316 | /**
1317 | * Gesture stopPropagation
1318 | * @param {type} e
1319 | * @returns {undefined}
1320 | */
1321 | $.stopPropagation = function(e) {
1322 | e.stopPropagation();
1323 | };
1324 |
1325 | /**
1326 | * register gesture
1327 | * @param {type} gesture
1328 | * @returns {$.gestures}
1329 | */
1330 | $.addGesture = function(gesture) {
1331 | return $.addAction('gestures', gesture);
1332 |
1333 | };
1334 |
1335 | var round = Math.round;
1336 | var abs = Math.abs;
1337 | var sqrt = Math.sqrt;
1338 | var atan = Math.atan;
1339 | var atan2 = Math.atan2;
1340 | /**
1341 | * distance
1342 | * @param {type} p1
1343 | * @param {type} p2
1344 | * @returns {Number}
1345 | */
1346 | var getDistance = function(p1, p2, props) {
1347 | if (!props) {
1348 | props = ['x', 'y'];
1349 | }
1350 | var x = p2[props[0]] - p1[props[0]];
1351 | var y = p2[props[1]] - p1[props[1]];
1352 | return sqrt((x * x) + (y * y));
1353 | };
1354 | /**
1355 | * scale
1356 | * @param {Object} starts
1357 | * @param {Object} moves
1358 | */
1359 | var getScale = function(starts, moves) {
1360 | if (starts.length >= 2 && moves.length >= 2) {
1361 | var props = ['pageX', 'pageY'];
1362 | return getDistance(moves[1], moves[0], props) / getDistance(starts[1], starts[0], props);
1363 | }
1364 | return 1;
1365 | };
1366 | /**
1367 | * angle
1368 | * @param {type} p1
1369 | * @param {type} p2
1370 | * @returns {Number}
1371 | */
1372 | var getAngle = function(p1, p2, props) {
1373 | if (!props) {
1374 | props = ['x', 'y'];
1375 | }
1376 | var x = p2[props[0]] - p1[props[0]];
1377 | var y = p2[props[1]] - p1[props[1]];
1378 | return atan2(y, x) * 180 / Math.PI;
1379 | };
1380 | /**
1381 | * direction
1382 | * @param {Object} x
1383 | * @param {Object} y
1384 | */
1385 | var getDirection = function(x, y) {
1386 | if (x === y) {
1387 | return '';
1388 | }
1389 | if (abs(x) >= abs(y)) {
1390 | return x > 0 ? 'left' : 'right';
1391 | }
1392 | return y > 0 ? 'up' : 'down';
1393 | };
1394 | /**
1395 | * rotation
1396 | * @param {Object} start
1397 | * @param {Object} end
1398 | */
1399 | var getRotation = function(start, end) {
1400 | var props = ['pageX', 'pageY'];
1401 | return getAngle(end[1], end[0], props) - getAngle(start[1], start[0], props);
1402 | };
1403 | /**
1404 | * px per ms
1405 | * @param {Object} deltaTime
1406 | * @param {Object} x
1407 | * @param {Object} y
1408 | */
1409 | var getVelocity = function(deltaTime, x, y) {
1410 | return {
1411 | x: x / deltaTime || 0,
1412 | y: y / deltaTime || 0
1413 | };
1414 | };
1415 | /**
1416 | * detect gestures
1417 | * @param {type} event
1418 | * @param {type} touch
1419 | * @returns {undefined}
1420 | */
1421 | var detect = function(event, touch) {
1422 | if ($.gestures.stoped) {
1423 | return;
1424 | }
1425 | $.doAction('gestures', function(index, gesture) {
1426 | if (!$.gestures.stoped) {
1427 | if ($.options.gestureConfig[gesture.name] !== false) {
1428 | gesture.handle(event, touch);
1429 | }
1430 | }
1431 | });
1432 | };
1433 | /**
1434 | * 暂时无用
1435 | * @param {Object} node
1436 | * @param {Object} parent
1437 | */
1438 | var hasParent = function(node, parent) {
1439 | while (node) {
1440 | if (node == parent) {
1441 | return true;
1442 | }
1443 | node = node.parentNode;
1444 | }
1445 | return false;
1446 | };
1447 |
1448 | var uniqueArray = function(src, key, sort) {
1449 | var results = [];
1450 | var values = [];
1451 | var i = 0;
1452 |
1453 | while (i < src.length) {
1454 | var val = key ? src[i][key] : src[i];
1455 | if (values.indexOf(val) < 0) {
1456 | results.push(src[i]);
1457 | }
1458 | values[i] = val;
1459 | i++;
1460 | }
1461 |
1462 | if (sort) {
1463 | if (!key) {
1464 | results = results.sort();
1465 | } else {
1466 | results = results.sort(function sortUniqueArray(a, b) {
1467 | return a[key] > b[key];
1468 | });
1469 | }
1470 | }
1471 |
1472 | return results;
1473 | };
1474 | var getMultiCenter = function(touches) {
1475 | var touchesLength = touches.length;
1476 | if (touchesLength === 1) {
1477 | return {
1478 | x: round(touches[0].pageX),
1479 | y: round(touches[0].pageY)
1480 | };
1481 | }
1482 |
1483 | var x = 0;
1484 | var y = 0;
1485 | var i = 0;
1486 | while (i < touchesLength) {
1487 | x += touches[i].pageX;
1488 | y += touches[i].pageY;
1489 | i++;
1490 | }
1491 |
1492 | return {
1493 | x: round(x / touchesLength),
1494 | y: round(y / touchesLength)
1495 | };
1496 | };
1497 | var multiTouch = function() {
1498 | return $.options.gestureConfig.pinch;
1499 | };
1500 | var copySimpleTouchData = function(touch) {
1501 | var touches = [];
1502 | var i = 0;
1503 | while (i < touch.touches.length) {
1504 | touches[i] = {
1505 | pageX: round(touch.touches[i].pageX),
1506 | pageY: round(touch.touches[i].pageY)
1507 | };
1508 | i++;
1509 | }
1510 | return {
1511 | timestamp: $.now(),
1512 | gesture: touch.gesture,
1513 | touches: touches,
1514 | center: getMultiCenter(touch.touches),
1515 | deltaX: touch.deltaX,
1516 | deltaY: touch.deltaY
1517 | };
1518 | };
1519 |
1520 | var calDelta = function(touch) {
1521 | var session = $.gestures.session;
1522 | var center = touch.center;
1523 | var offset = session.offsetDelta || {};
1524 | var prevDelta = session.prevDelta || {};
1525 | var prevTouch = session.prevTouch || {};
1526 |
1527 | if (touch.gesture.type === $.EVENT_START || touch.gesture.type === $.EVENT_END) {
1528 | prevDelta = session.prevDelta = {
1529 | x: prevTouch.deltaX || 0,
1530 | y: prevTouch.deltaY || 0
1531 | };
1532 |
1533 | offset = session.offsetDelta = {
1534 | x: center.x,
1535 | y: center.y
1536 | };
1537 | }
1538 | touch.deltaX = prevDelta.x + (center.x - offset.x);
1539 | touch.deltaY = prevDelta.y + (center.y - offset.y);
1540 | };
1541 | var calTouchData = function(touch) {
1542 | var session = $.gestures.session;
1543 | var touches = touch.touches;
1544 | var touchesLength = touches.length;
1545 |
1546 | if (!session.firstTouch) {
1547 | session.firstTouch = copySimpleTouchData(touch);
1548 | }
1549 |
1550 | if (multiTouch() && touchesLength > 1 && !session.firstMultiTouch) {
1551 | session.firstMultiTouch = copySimpleTouchData(touch);
1552 | } else if (touchesLength === 1) {
1553 | session.firstMultiTouch = false;
1554 | }
1555 |
1556 | var firstTouch = session.firstTouch;
1557 | var firstMultiTouch = session.firstMultiTouch;
1558 | var offsetCenter = firstMultiTouch ? firstMultiTouch.center : firstTouch.center;
1559 |
1560 | var center = touch.center = getMultiCenter(touches);
1561 | touch.timestamp = $.now();
1562 | touch.deltaTime = touch.timestamp - firstTouch.timestamp;
1563 |
1564 | touch.angle = getAngle(offsetCenter, center);
1565 | touch.distance = getDistance(offsetCenter, center);
1566 |
1567 | calDelta(touch);
1568 |
1569 | touch.offsetDirection = getDirection(touch.deltaX, touch.deltaY);
1570 |
1571 | touch.scale = firstMultiTouch ? getScale(firstMultiTouch.touches, touches) : 1;
1572 | touch.rotation = firstMultiTouch ? getRotation(firstMultiTouch.touches, touches) : 0;
1573 |
1574 | calIntervalTouchData(touch);
1575 |
1576 | };
1577 | var CAL_INTERVAL = 25;
1578 | var calIntervalTouchData = function(touch) {
1579 | var session = $.gestures.session;
1580 | var last = session.lastInterval || touch;
1581 | var deltaTime = touch.timestamp - last.timestamp;
1582 | var velocity;
1583 | var velocityX;
1584 | var velocityY;
1585 | var direction;
1586 |
1587 | if (touch.gesture.type != $.EVENT_CANCEL && (deltaTime > CAL_INTERVAL || last.velocity === undefined)) {
1588 | var deltaX = last.deltaX - touch.deltaX;
1589 | var deltaY = last.deltaY - touch.deltaY;
1590 |
1591 | var v = getVelocity(deltaTime, deltaX, deltaY);
1592 | velocityX = v.x;
1593 | velocityY = v.y;
1594 | velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y;
1595 | direction = getDirection(deltaX, deltaY) || last.direction;
1596 |
1597 | session.lastInterval = touch;
1598 | } else {
1599 | velocity = last.velocity;
1600 | velocityX = last.velocityX;
1601 | velocityY = last.velocityY;
1602 | direction = last.direction;
1603 | }
1604 |
1605 | touch.velocity = velocity;
1606 | touch.velocityX = velocityX;
1607 | touch.velocityY = velocityY;
1608 | touch.direction = direction;
1609 | };
1610 | var targetIds = {};
1611 | var convertTouches = function(touches) {
1612 | for (var i = 0; i < touches.length; i++) {
1613 | !touches['identifier'] && (touches['identifier'] = 0);
1614 | }
1615 | return touches;
1616 | };
1617 | var getTouches = function(event, touch) {
1618 | var allTouches = convertTouches($.slice.call(event.touches || [event]));
1619 |
1620 | var type = event.type;
1621 |
1622 | var targetTouches = [];
1623 | var changedTargetTouches = [];
1624 |
1625 | //当touchstart或touchmove且touches长度为1,直接获得all和changed
1626 | if ((type === $.EVENT_START || type === $.EVENT_MOVE) && allTouches.length === 1) {
1627 | targetIds[allTouches[0].identifier] = true;
1628 | targetTouches = allTouches;
1629 | changedTargetTouches = allTouches;
1630 | touch.target = event.target;
1631 | } else {
1632 | var i = 0;
1633 | var targetTouches = [];
1634 | var changedTargetTouches = [];
1635 | var changedTouches = convertTouches($.slice.call(event.changedTouches || [event]));
1636 |
1637 | touch.target = event.target;
1638 | var sessionTarget = $.gestures.session.target || event.target;
1639 | targetTouches = allTouches.filter(function(touch) {
1640 | return hasParent(touch.target, sessionTarget);
1641 | });
1642 |
1643 | if (type === $.EVENT_START) {
1644 | i = 0;
1645 | while (i < targetTouches.length) {
1646 | targetIds[targetTouches[i].identifier] = true;
1647 | i++;
1648 | }
1649 | }
1650 |
1651 | i = 0;
1652 | while (i < changedTouches.length) {
1653 | if (targetIds[changedTouches[i].identifier]) {
1654 | changedTargetTouches.push(changedTouches[i]);
1655 | }
1656 | if (type === $.EVENT_END || type === $.EVENT_CANCEL) {
1657 | delete targetIds[changedTouches[i].identifier];
1658 | }
1659 | i++;
1660 | }
1661 |
1662 | if (!changedTargetTouches.length) {
1663 | return false;
1664 | }
1665 | }
1666 | targetTouches = uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true);
1667 | var touchesLength = targetTouches.length;
1668 | var changedTouchesLength = changedTargetTouches.length;
1669 | if (type === $.EVENT_START && touchesLength - changedTouchesLength === 0) { //first
1670 | touch.isFirst = true;
1671 | $.gestures.touch = $.gestures.session = {
1672 | target: event.target
1673 | };
1674 | }
1675 | touch.isFinal = ((type === $.EVENT_END || type === $.EVENT_CANCEL) && (touchesLength - changedTouchesLength === 0));
1676 |
1677 | touch.touches = targetTouches;
1678 | touch.changedTouches = changedTargetTouches;
1679 | return true;
1680 |
1681 | };
1682 | var handleTouchEvent = function(event) {
1683 | var touch = {
1684 | gesture: event
1685 | };
1686 | var touches = getTouches(event, touch);
1687 | if (!touches) {
1688 | return;
1689 | }
1690 | calTouchData(touch);
1691 | detect(event, touch);
1692 | $.gestures.session.prevTouch = touch;
1693 | if (event.type === $.EVENT_END && !$.isTouchable) {
1694 | $.gestures.touch = $.gestures.session = {};
1695 | }
1696 | };
1697 | window.addEventListener($.EVENT_START, handleTouchEvent);
1698 | window.addEventListener($.EVENT_MOVE, handleTouchEvent);
1699 | window.addEventListener($.EVENT_END, handleTouchEvent);
1700 | window.addEventListener($.EVENT_CANCEL, handleTouchEvent);
1701 | //fixed hashchange(android)
1702 | window.addEventListener($.EVENT_CLICK, function(e) {
1703 | //TODO 应该判断当前target是不是在targets.popover内部,而不是非要相等
1704 | if (($.os.android || $.os.ios) && (($.targets.popover && e.target === $.targets.popover) || ($.targets.tab) || $.targets.offcanvas || $.targets.modal)) {
1705 | e.preventDefault();
1706 | }
1707 | }, true);
1708 |
1709 |
1710 | //增加原生滚动识别
1711 | $.isScrolling = false;
1712 | var scrollingTimeout = null;
1713 | window.addEventListener('scroll', function() {
1714 | $.isScrolling = true;
1715 | scrollingTimeout && clearTimeout(scrollingTimeout);
1716 | scrollingTimeout = setTimeout(function() {
1717 | $.isScrolling = false;
1718 | }, 250);
1719 | });
1720 | })(mui, window);
1721 |
1722 |
1723 | /**
1724 | * mui gesture tap and doubleTap
1725 | * @param {type} $
1726 | * @param {type} name
1727 | * @returns {undefined}
1728 | */
1729 | (function($, name) {
1730 | var lastTarget;
1731 | var lastTapTime;
1732 | var handle = function(event, touch) {
1733 | var session = $.gestures.session;
1734 | var options = this.options;
1735 | switch (event.type) {
1736 | case $.EVENT_END:
1737 | if (!touch.isFinal) {
1738 | return;
1739 | }
1740 | var target = session.target;
1741 | if (!target || (target.disabled || (target.classList && target.classList.contains($.className('disabled'))))) {
1742 | return;
1743 | }
1744 | if (touch.distance < options.tapMaxDistance && touch.deltaTime < options.tapMaxTime) {
1745 | if ($.options.gestureConfig.doubletap && lastTarget && (lastTarget === target)) { //same target
1746 | if (lastTapTime && (touch.timestamp - lastTapTime) < options.tapMaxInterval) {
1747 | $.trigger(target, 'doubletap', touch);
1748 | lastTapTime = $.now();
1749 | lastTarget = target;
1750 | return;
1751 | }
1752 | }
1753 | $.trigger(target, name, touch);
1754 | lastTapTime = $.now();
1755 | lastTarget = target;
1756 | }
1757 | break;
1758 | }
1759 | };
1760 | /**
1761 | * mui gesture tap
1762 | */
1763 | $.addGesture({
1764 | name: name,
1765 | index: 30,
1766 | handle: handle,
1767 | options: {
1768 | fingers: 1,
1769 | tapMaxInterval: 300,
1770 | tapMaxDistance: 5,
1771 | tapMaxTime: 250
1772 | }
1773 | });
1774 | })(mui, 'tap');
1775 |
1776 |
1777 | export default mui;
1778 |
--------------------------------------------------------------------------------