mui.picker.all.js 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941
  1. /**
  2. * 选择列表插件
  3. * varstion 2.0.0
  4. * by Houfeng
  5. * Houfeng@DCloud.io
  6. */
  7. (function($, window, document, undefined) {
  8. var MAX_EXCEED = 30;
  9. var VISIBLE_RANGE = 90;
  10. var DEFAULT_ITEM_HEIGHT = 40;
  11. var BLUR_WIDTH = 10;
  12. var rad2deg = $.rad2deg = function(rad) {
  13. return rad / (Math.PI / 180);
  14. };
  15. var deg2rad = $.deg2rad = function(deg) {
  16. return deg * (Math.PI / 180);
  17. };
  18. var platform = navigator.platform.toLowerCase();
  19. var userAgent = navigator.userAgent.toLowerCase();
  20. var isIos = (userAgent.indexOf('iphone') > -1 ||
  21. userAgent.indexOf('ipad') > -1 ||
  22. userAgent.indexOf('ipod') > -1) &&
  23. (platform.indexOf('iphone') > -1 ||
  24. platform.indexOf('ipad') > -1 ||
  25. platform.indexOf('ipod') > -1);
  26. //alert(isIos);
  27. var Picker = $.Picker = function(holder, options) {
  28. var self = this;
  29. self.holder = holder;
  30. self.options = options || {};
  31. self.init();
  32. self.initInertiaParams();
  33. self.calcElementItemPostion(true);
  34. self.bindEvent();
  35. };
  36. Picker.prototype.findElementItems = function() {
  37. var self = this;
  38. self.elementItems = [].slice.call(self.holder.querySelectorAll('li'));
  39. return self.elementItems;
  40. };
  41. Picker.prototype.init = function() {
  42. var self = this;
  43. self.list = self.holder.querySelector('ul');
  44. self.findElementItems();
  45. self.height = self.holder.offsetHeight;
  46. self.r = self.height / 2 - BLUR_WIDTH;
  47. self.d = self.r * 2;
  48. self.itemHeight = self.elementItems.length > 0 ? self.elementItems[0].offsetHeight : DEFAULT_ITEM_HEIGHT;
  49. self.itemAngle = parseInt(self.calcAngle(self.itemHeight * 0.8));
  50. self.hightlightRange = self.itemAngle / 2;
  51. self.visibleRange = VISIBLE_RANGE;
  52. self.beginAngle = 0;
  53. self.beginExceed = self.beginAngle - MAX_EXCEED;
  54. self.list.angle = self.beginAngle;
  55. if (isIos) {
  56. self.list.style.webkitTransformOrigin = "center center " + self.r + "px";
  57. }
  58. };
  59. Picker.prototype.calcElementItemPostion = function(andGenerateItms) {
  60. var self = this;
  61. if (andGenerateItms) {
  62. self.items = [];
  63. }
  64. self.elementItems.forEach(function(item) {
  65. var index = self.elementItems.indexOf(item);
  66. self.endAngle = self.itemAngle * index;
  67. item.angle = self.endAngle;
  68. item.style.webkitTransformOrigin = "center center -" + self.r + "px";
  69. item.style.webkitTransform = "translateZ(" + self.r + "px) rotateX(" + (-self.endAngle) + "deg)";
  70. if (andGenerateItms) {
  71. var dataItem = {};
  72. dataItem.text = item.innerHTML || '';
  73. dataItem.value = item.getAttribute('data-value') || dataItem.text;
  74. self.items.push(dataItem);
  75. }
  76. });
  77. self.endExceed = self.endAngle + MAX_EXCEED;
  78. self.calcElementItemVisibility(self.beginAngle);
  79. };
  80. Picker.prototype.calcAngle = function(c) {
  81. var self = this;
  82. var a = b = parseFloat(self.r);
  83. //直径的整倍数部分直接乘以 180
  84. c = Math.abs(c); //只算角度不关心正否值
  85. var intDeg = parseInt(c / self.d) * 180;
  86. c = c % self.d;
  87. //余弦
  88. var cosC = (a * a + b * b - c * c) / (2 * a * b);
  89. var angleC = intDeg + rad2deg(Math.acos(cosC));
  90. return angleC;
  91. };
  92. Picker.prototype.calcElementItemVisibility = function(angle) {
  93. var self = this;
  94. self.elementItems.forEach(function(item) {
  95. var difference = Math.abs(item.angle - angle);
  96. if (difference < self.hightlightRange) {
  97. item.classList.add('highlight');
  98. } else if (difference < self.visibleRange) {
  99. item.classList.add('visible');
  100. item.classList.remove('highlight');
  101. } else {
  102. item.classList.remove('highlight');
  103. item.classList.remove('visible');
  104. }
  105. });
  106. };
  107. Picker.prototype.setAngle = function(angle) {
  108. var self = this;
  109. self.list.angle = angle;
  110. self.list.style.webkitTransform = "perspective(1000px) rotateY(0deg) rotateX(" + angle + "deg)";
  111. self.calcElementItemVisibility(angle);
  112. };
  113. Picker.prototype.bindEvent = function() {
  114. var self = this;
  115. var lastAngle = 0;
  116. var startY = null;
  117. self.holder.addEventListener('touchstart', function(event) {
  118. event.preventDefault();
  119. self.list.style.webkitTransition = '';
  120. startY = (event.changedTouches ? event.changedTouches[0] : event).pageY;
  121. lastAngle = self.list.angle;
  122. self.updateInertiaParams(event, true);
  123. }, false);
  124. self.holder.addEventListener('touchend', function(event) {
  125. event.preventDefault();
  126. self.startInertiaScroll(event);
  127. }, false);
  128. self.holder.addEventListener('touchcancel', function(event) {
  129. event.preventDefault();
  130. self.startInertiaScroll(event);
  131. }, false);
  132. self.holder.addEventListener('touchmove', function(event) {
  133. event.preventDefault();
  134. var endY = (event.changedTouches ? event.changedTouches[0] : event).pageY;
  135. var dragRange = endY - startY;
  136. var dragAngle = self.calcAngle(dragRange);
  137. var newAngle = dragRange > 0 ? lastAngle - dragAngle : lastAngle + dragAngle;
  138. if (newAngle > self.endExceed) {
  139. newAngle = self.endExceed
  140. }
  141. if (newAngle < self.beginExceed) {
  142. newAngle = self.beginExceed
  143. }
  144. self.setAngle(newAngle);
  145. self.updateInertiaParams(event);
  146. }, false);
  147. //--
  148. self.list.addEventListener('tap', function(event) {
  149. elementItem = event.target;
  150. if (elementItem.tagName == 'LI') {
  151. self.setSelectedIndex(self.elementItems.indexOf(elementItem), 200);
  152. }
  153. }, false);
  154. };
  155. Picker.prototype.initInertiaParams = function() {
  156. var self = this;
  157. self.lastMoveTime = 0;
  158. self.lastMoveStart = 0;
  159. self.stopInertiaMove = false;
  160. };
  161. Picker.prototype.updateInertiaParams = function(event, isStart) {
  162. var self = this;
  163. var point = event.changedTouches ? event.changedTouches[0] : event;
  164. if (isStart) {
  165. self.lastMoveStart = point.pageY;
  166. self.lastMoveTime = event.timeStamp || Date.now();
  167. self.startAngle = self.list.angle;
  168. } else {
  169. var nowTime = event.timeStamp || Date.now();
  170. if (nowTime - self.lastMoveTime > 300) {
  171. self.lastMoveTime = nowTime;
  172. self.lastMoveStart = point.pageY;
  173. }
  174. }
  175. self.stopInertiaMove = true;
  176. };
  177. Picker.prototype.startInertiaScroll = function(event) {
  178. var self = this;
  179. var point = event.changedTouches ? event.changedTouches[0] : event;
  180. /**
  181. * 缓动代码
  182. */
  183. var nowTime = event.timeStamp || Date.now();
  184. var v = (point.pageY - self.lastMoveStart) / (nowTime - self.lastMoveTime); //最后一段时间手指划动速度
  185. var dir = v > 0 ? -1 : 1; //加速度方向
  186. var deceleration = dir * 0.0006 * -1;
  187. var duration = Math.abs(v / deceleration); // 速度消减至0所需时间
  188. var dist = v * duration / 2; //最终移动多少
  189. var startAngle = self.list.angle;
  190. var distAngle = self.calcAngle(dist) * dir;
  191. //----
  192. var srcDistAngle = distAngle;
  193. if (startAngle + distAngle < self.beginExceed) {
  194. distAngle = self.beginExceed - startAngle;
  195. duration = duration * (distAngle / srcDistAngle) * 0.6;
  196. }
  197. if (startAngle + distAngle > self.endExceed) {
  198. distAngle = self.endExceed - startAngle;
  199. duration = duration * (distAngle / srcDistAngle) * 0.6;
  200. }
  201. //----
  202. if (distAngle == 0) {
  203. self.endScroll();
  204. return;
  205. }
  206. self.scrollDistAngle(nowTime, startAngle, distAngle, duration);
  207. };
  208. Picker.prototype.scrollDistAngle = function(nowTime, startAngle, distAngle, duration) {
  209. var self = this;
  210. self.stopInertiaMove = false;
  211. (function(nowTime, startAngle, distAngle, duration) {
  212. var frameInterval = 13;
  213. var stepCount = duration / frameInterval;
  214. var stepIndex = 0;
  215. (function inertiaMove() {
  216. if (self.stopInertiaMove) return;
  217. var newAngle = self.quartEaseOut(stepIndex, startAngle, distAngle, stepCount);
  218. self.setAngle(newAngle);
  219. stepIndex++;
  220. if (stepIndex > stepCount - 1 || newAngle < self.beginExceed || newAngle > self.endExceed) {
  221. self.endScroll();
  222. return;
  223. }
  224. setTimeout(inertiaMove, frameInterval);
  225. })();
  226. })(nowTime, startAngle, distAngle, duration);
  227. };
  228. Picker.prototype.quartEaseOut = function(t, b, c, d) {
  229. return -c * ((t = t / d - 1) * t * t * t - 1) + b;
  230. };
  231. Picker.prototype.endScroll = function() {
  232. var self = this;
  233. if (self.list.angle < self.beginAngle) {
  234. self.list.style.webkitTransition = "150ms ease-out";
  235. self.setAngle(self.beginAngle);
  236. } else if (self.list.angle > self.endAngle) {
  237. self.list.style.webkitTransition = "150ms ease-out";
  238. self.setAngle(self.endAngle);
  239. } else {
  240. var index = parseInt((self.list.angle / self.itemAngle).toFixed(0));
  241. self.list.style.webkitTransition = "100ms ease-out";
  242. self.setAngle(self.itemAngle * index);
  243. }
  244. self.triggerChange();
  245. };
  246. Picker.prototype.triggerChange = function(force) {
  247. var self = this;
  248. setTimeout(function() {
  249. var index = self.getSelectedIndex();
  250. var item = self.items[index];
  251. if ($.trigger && (index != self.lastIndex || force)) {
  252. $.trigger(self.holder, 'change', {
  253. "index": index,
  254. "item": item
  255. });
  256. //console.log('change:' + index);
  257. }
  258. self.lastIndex = index;
  259. }, 0);
  260. };
  261. Picker.prototype.correctAngle = function(angle) {
  262. var self = this;
  263. if (angle < self.beginAngle) {
  264. return self.beginAngle;
  265. } else if (angle > self.endAngle) {
  266. return self.endAngle;
  267. } else {
  268. return angle;
  269. }
  270. };
  271. Picker.prototype.setItems = function(items) {
  272. var self = this;
  273. self.items = items || [];
  274. var buffer = [];
  275. self.items.forEach(function(item) {
  276. if (item !== null && item !== undefined) {
  277. buffer.push('<li>' + (item.text || item) + '</li>');
  278. }
  279. });
  280. self.list.innerHTML = buffer.join('');
  281. self.findElementItems();
  282. self.calcElementItemPostion();
  283. self.setAngle(self.correctAngle(self.list.angle));
  284. self.triggerChange(true);
  285. };
  286. Picker.prototype.getItems = function() {
  287. var self = this;
  288. return self.items;
  289. };
  290. Picker.prototype.getSelectedIndex = function() {
  291. var self = this;
  292. return parseInt((self.list.angle / self.itemAngle).toFixed(0));
  293. };
  294. Picker.prototype.setSelectedIndex = function(index, duration) {
  295. var self = this;
  296. self.list.style.webkitTransition = '';
  297. var angle = self.correctAngle(self.itemAngle * index);
  298. if (duration && duration > 0) {
  299. var distAngle = angle - self.list.angle;
  300. self.scrollDistAngle(Date.now(), self.list.angle, distAngle, duration);
  301. } else {
  302. self.setAngle(angle);
  303. }
  304. self.triggerChange();
  305. };
  306. Picker.prototype.getSelectedItem = function() {
  307. var self = this;
  308. return self.items[self.getSelectedIndex()];
  309. };
  310. Picker.prototype.getSelectedValue = function() {
  311. var self = this;
  312. return (self.items[self.getSelectedIndex()] || {}).value;
  313. };
  314. Picker.prototype.getSelectedText = function() {
  315. var self = this;
  316. return (self.items[self.getSelectedIndex()] || {}).text;
  317. };
  318. Picker.prototype.setSelectedValue = function(value, duration) {
  319. var self = this;
  320. for (var index in self.items) {
  321. var item = self.items[index];
  322. if (item.value == value) {
  323. self.setSelectedIndex(index, duration);
  324. return;
  325. }
  326. }
  327. };
  328. if ($.fn) {
  329. $.fn.picker = function(options) {
  330. //遍历选择的元素
  331. this.each(function(i, element) {
  332. if (element.picker) return;
  333. if (options) {
  334. element.picker = new Picker(element, options);
  335. } else {
  336. var optionsText = element.getAttribute('data-picker-options');
  337. var _options = optionsText ? JSON.parse(optionsText) : {};
  338. element.picker = new Picker(element, _options);
  339. }
  340. });
  341. return this[0] ? this[0].picker : null;
  342. };
  343. //自动初始化
  344. $.ready(function() {
  345. $('.mui-picker').picker();
  346. });
  347. }
  348. })(window.mui || window, window, document, undefined);
  349. //end
  350. /**
  351. * 弹出选择列表插件
  352. * 此组件依赖 listpcker ,请在页面中先引入 mui.picker.css + mui.picker.js
  353. * varstion 1.0.1
  354. * by Houfeng
  355. * Houfeng@DCloud.io
  356. */
  357. (function($, document) {
  358. //创建 DOM
  359. $.dom = function(str) {
  360. if (typeof(str) !== 'string') {
  361. if ((str instanceof Array) || (str[0] && str.length)) {
  362. return [].slice.call(str);
  363. } else {
  364. return [str];
  365. }
  366. }
  367. if (!$.__create_dom_div__) {
  368. $.__create_dom_div__ = document.createElement('div');
  369. }
  370. $.__create_dom_div__.innerHTML = str;
  371. return [].slice.call($.__create_dom_div__.childNodes);
  372. };
  373. var panelBuffer = '<div class="mui-poppicker">\
  374. <div class="mui-poppicker-header">\
  375. <button class="mui-btn mui-poppicker-btn-cancel">取消</button>\
  376. <button class="mui-btn mui-btn-blue mui-poppicker-btn-ok">确定</button>\
  377. <div class="mui-poppicker-clear"></div>\
  378. </div>\
  379. <div class="mui-poppicker-body">\
  380. </div>\
  381. </div>';
  382. var pickerBuffer = '<div class="mui-picker">\
  383. <div class="mui-picker-inner">\
  384. <div class="mui-pciker-rule mui-pciker-rule-ft"></div>\
  385. <ul class="mui-pciker-list">\
  386. </ul>\
  387. <div class="mui-pciker-rule mui-pciker-rule-bg"></div>\
  388. </div>\
  389. </div>';
  390. //定义弹出选择器类
  391. var PopPicker = $.PopPicker = $.Class.extend({
  392. //构造函数
  393. init: function(options) {
  394. var self = this;
  395. self.options = options || {};
  396. self.options.buttons = self.options.buttons || ['取消', '确定'];
  397. self.panel = $.dom(panelBuffer)[0];
  398. document.body.appendChild(self.panel);
  399. self.ok = self.panel.querySelector('.mui-poppicker-btn-ok');
  400. self.cancel = self.panel.querySelector('.mui-poppicker-btn-cancel');
  401. self.body = self.panel.querySelector('.mui-poppicker-body');
  402. self.mask = $.createMask();
  403. self.cancel.innerText = self.options.buttons[0];
  404. self.ok.innerText = self.options.buttons[1];
  405. self.cancel.addEventListener('tap', function(event) {
  406. self.hide();
  407. }, false);
  408. self.ok.addEventListener('tap', function(event) {
  409. if (self.callback) {
  410. var rs = self.callback(self.getSelectedItems());
  411. if (rs !== false) {
  412. self.hide();
  413. }
  414. }
  415. }, false);
  416. self.mask[0].addEventListener('tap', function() {
  417. self.hide();
  418. }, false);
  419. self._createPicker();
  420. //防止滚动穿透
  421. self.panel.addEventListener('touchstart', function(event) {
  422. event.preventDefault();
  423. }, false);
  424. self.panel.addEventListener('touchmove', function(event) {
  425. event.preventDefault();
  426. }, false);
  427. },
  428. _createPicker: function() {
  429. var self = this;
  430. var layer = self.options.layer || 1;
  431. var width = (100 / layer) + '%';
  432. self.pickers = [];
  433. for (var i = 1; i <= layer; i++) {
  434. var pickerElement = $.dom(pickerBuffer)[0];
  435. pickerElement.style.width = width;
  436. self.body.appendChild(pickerElement);
  437. var picker = $(pickerElement).picker();
  438. self.pickers.push(picker);
  439. pickerElement.addEventListener('change', function(event) {
  440. var nextPickerElement = this.nextSibling;
  441. if (nextPickerElement && nextPickerElement.picker) {
  442. var eventData = event.detail || {};
  443. var preItem = eventData.item || {};
  444. nextPickerElement.picker.setItems(preItem.children);
  445. }
  446. }, false);
  447. }
  448. },
  449. //填充数据
  450. setData: function(data) {
  451. var self = this;
  452. data = data || [];
  453. self.pickers[0].setItems(data);
  454. },
  455. //获取选中的项(数组)
  456. getSelectedItems: function() {
  457. var self = this;
  458. var items = [];
  459. for (var i in self.pickers) {
  460. var picker = self.pickers[i];
  461. items.push(picker.getSelectedItem() || {});
  462. }
  463. return items;
  464. },
  465. //显示
  466. show: function(callback) {
  467. var self = this;
  468. self.callback = callback;
  469. self.mask.show();
  470. document.body.classList.add($.className('poppicker-active-for-page'));
  471. self.panel.classList.add($.className('active'));
  472. //处理物理返回键
  473. self.__back = $.back;
  474. $.back = function() {
  475. self.hide();
  476. };
  477. },
  478. //隐藏
  479. hide: function() {
  480. var self = this;
  481. if (self.disposed) return;
  482. self.panel.classList.remove($.className('active'));
  483. self.mask.close();
  484. document.body.classList.remove($.className('poppicker-active-for-page'));
  485. //处理物理返回键
  486. $.back=self.__back;
  487. },
  488. dispose: function() {
  489. var self = this;
  490. self.hide();
  491. setTimeout(function() {
  492. self.panel.parentNode.removeChild(self.panel);
  493. for (var name in self) {
  494. self[name] = null;
  495. delete self[name];
  496. };
  497. self.disposed = true;
  498. }, 300);
  499. }
  500. });
  501. })(mui, document);
  502. /**
  503. * 日期时间插件
  504. * varstion 1.0.5
  505. * by Houfeng
  506. * Houfeng@DCloud.io
  507. */
  508. (function($, document) {
  509. //创建 DOM
  510. $.dom = function(str) {
  511. if (typeof(str) !== 'string') {
  512. if ((str instanceof Array) || (str[0] && str.length)) {
  513. return [].slice.call(str);
  514. } else {
  515. return [str];
  516. }
  517. }
  518. if (!$.__create_dom_div__) {
  519. $.__create_dom_div__ = document.createElement('div');
  520. }
  521. $.__create_dom_div__.innerHTML = str;
  522. return [].slice.call($.__create_dom_div__.childNodes);
  523. };
  524. var domBuffer = '<div class="mui-dtpicker" data-type="datetime">\
  525. <div class="mui-dtpicker-header">\
  526. <button data-id="btn-cancel" class="mui-btn">取消</button>\
  527. <button data-id="btn-ok" class="mui-btn mui-btn-blue">确定</button>\
  528. </div>\
  529. <div class="mui-dtpicker-title"><h5 data-id="title-y">年</h5><h5 data-id="title-m">月</h5><h5 data-id="title-d">日</h5><h5 data-id="title-h">时</h5><h5 data-id="title-i">分</h5></div>\
  530. <div class="mui-dtpicker-body">\
  531. <div data-id="picker-y" class="mui-picker">\
  532. <div class="mui-picker-inner">\
  533. <div class="mui-pciker-rule mui-pciker-rule-ft"></div>\
  534. <ul class="mui-pciker-list">\
  535. </ul>\
  536. <div class="mui-pciker-rule mui-pciker-rule-bg"></div>\
  537. </div>\
  538. </div>\
  539. <div data-id="picker-m" class="mui-picker">\
  540. <div class="mui-picker-inner">\
  541. <div class="mui-pciker-rule mui-pciker-rule-ft"></div>\
  542. <ul class="mui-pciker-list">\
  543. </ul>\
  544. <div class="mui-pciker-rule mui-pciker-rule-bg"></div>\
  545. </div>\
  546. </div>\
  547. <div data-id="picker-d" class="mui-picker">\
  548. <div class="mui-picker-inner">\
  549. <div class="mui-pciker-rule mui-pciker-rule-ft"></div>\
  550. <ul class="mui-pciker-list">\
  551. </ul>\
  552. <div class="mui-pciker-rule mui-pciker-rule-bg"></div>\
  553. </div>\
  554. </div>\
  555. <div data-id="picker-h" class="mui-picker">\
  556. <div class="mui-picker-inner">\
  557. <div class="mui-pciker-rule mui-pciker-rule-ft"></div>\
  558. <ul class="mui-pciker-list">\
  559. </ul>\
  560. <div class="mui-pciker-rule mui-pciker-rule-bg"></div>\
  561. </div>\
  562. </div>\
  563. <div data-id="picker-i" class="mui-picker">\
  564. <div class="mui-picker-inner">\
  565. <div class="mui-pciker-rule mui-pciker-rule-ft"></div>\
  566. <ul class="mui-pciker-list">\
  567. </ul>\
  568. <div class="mui-pciker-rule mui-pciker-rule-bg"></div>\
  569. </div>\
  570. </div>\
  571. </div>\
  572. </div>';
  573. //plugin
  574. var DtPicker = $.DtPicker = $.Class.extend({
  575. init: function(options) {
  576. var self = this;
  577. var _picker = $.dom(domBuffer)[0];
  578. document.body.appendChild(_picker);
  579. $('[data-id*="picker"]', _picker).picker();
  580. var ui = self.ui = {
  581. picker: _picker,
  582. mask: $.createMask(),
  583. ok: $('[data-id="btn-ok"]', _picker)[0],
  584. cancel: $('[data-id="btn-cancel"]', _picker)[0],
  585. y: $('[data-id="picker-y"]', _picker)[0],
  586. m: $('[data-id="picker-m"]', _picker)[0],
  587. d: $('[data-id="picker-d"]', _picker)[0],
  588. h: $('[data-id="picker-h"]', _picker)[0],
  589. i: $('[data-id="picker-i"]', _picker)[0],
  590. labels: $('[data-id*="title-"]', _picker),
  591. };
  592. ui.cancel.addEventListener('tap', function() {
  593. self.hide();
  594. }, false);
  595. ui.ok.addEventListener('tap', function() {
  596. var rs = self.callback(self.getSelected());
  597. if (rs !== false) {
  598. self.hide();
  599. }
  600. }, false);
  601. ui.y.addEventListener('change', function() {
  602. self._createDay();
  603. }, false);
  604. ui.m.addEventListener('change', function() {
  605. self._createDay();
  606. }, false);
  607. ui.mask[0].addEventListener('tap', function() {
  608. self.hide();
  609. }, false);
  610. self._create(options);
  611. //防止滚动穿透
  612. self.ui.picker.addEventListener('touchstart',function(event){
  613. event.preventDefault();
  614. },false);
  615. self.ui.picker.addEventListener('touchmove',function(event){
  616. event.preventDefault();
  617. },false);
  618. },
  619. getSelected: function() {
  620. var self = this;
  621. var ui = self.ui;
  622. var type = self.options.type;
  623. var selected = {
  624. type: type,
  625. y: ui.y.picker.getSelectedItem(),
  626. m: ui.m.picker.getSelectedItem(),
  627. d: ui.d.picker.getSelectedItem(),
  628. h: ui.h.picker.getSelectedItem(),
  629. i: ui.i.picker.getSelectedItem(),
  630. toString: function() {
  631. return this.value;
  632. }
  633. };
  634. switch (type) {
  635. case 'datetime':
  636. selected.value = selected.y.value + '-' + selected.m.value + '-' + selected.d.value + ' ' + selected.h.value + ':' + selected.i.value;
  637. selected.text = selected.y.text + '-' + selected.m.text + '-' + selected.d.text + ' ' + selected.h.text + ':' + selected.i.text;
  638. break;
  639. case 'date':
  640. selected.value = selected.y.value + '-' + selected.m.value + '-' + selected.d.value;
  641. selected.text = selected.y.text + '-' + selected.m.text + '-' + selected.d.text;
  642. break;
  643. case 'time':
  644. selected.value = selected.h.value + ':' + selected.i.value;
  645. selected.text = selected.h.text + ':' + selected.i.text;
  646. break;
  647. case 'month':
  648. selected.value = selected.y.value + '-' + selected.m.value;
  649. selected.text = selected.y.text + '-' + selected.m.text;
  650. break;
  651. case 'hour':
  652. selected.value = selected.y.value + '-' + selected.m.value + '-' + selected.d.value + ' ' + selected.h.value;
  653. selected.text = selected.y.text + '-' + selected.m.text + '-' + selected.d.text + ' ' + selected.h.text;
  654. break;
  655. }
  656. return selected;
  657. },
  658. setSelectedValue: function(value) {
  659. var self = this;
  660. var ui = self.ui;
  661. var parsedValue = self._parseValue(value);
  662. ui.y.picker.setSelectedValue(parsedValue.y, 0);
  663. ui.m.picker.setSelectedValue(parsedValue.m, 0);
  664. ui.d.picker.setSelectedValue(parsedValue.d, 0);
  665. ui.h.picker.setSelectedValue(parsedValue.h, 0);
  666. ui.i.picker.setSelectedValue(parsedValue.i, 0);
  667. },
  668. isLeapYear: function(year) {
  669. return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
  670. },
  671. _inArray: function(array, item) {
  672. for (var index in array) {
  673. var _item = array[index];
  674. if (_item === item) return true;
  675. }
  676. return false;
  677. },
  678. getDayNum: function(year, month) {
  679. var self = this;
  680. if (self._inArray([1, 3, 5, 7, 8, 10, 12], month)) {
  681. return 31;
  682. } else if (self._inArray([4, 6, 9, 11], month)) {
  683. return 30;
  684. } else if (self.isLeapYear(year)) {
  685. return 29;
  686. } else {
  687. return 28;
  688. }
  689. },
  690. _fill: function(num) {
  691. num = num.toString();
  692. if (num.length < 2) {
  693. num = 0 + num;
  694. }
  695. return num;
  696. },
  697. _createYear: function(current) {
  698. var self = this;
  699. var options = self.options;
  700. var ui = self.ui;
  701. //生成年列表
  702. var yArray = [];
  703. if (options.customData.y) {
  704. yArray = options.customData.y;
  705. } else {
  706. var yBegin = options.beginYear;
  707. var yEnd = options.endYear;
  708. for (var y = yBegin; y <= yEnd; y++) {
  709. yArray.push({
  710. text: y + '',
  711. value: y
  712. });
  713. }
  714. }
  715. ui.y.picker.setItems(yArray);
  716. //ui.y.picker.setSelectedValue(current);
  717. },
  718. _createMonth: function(current) {
  719. var self = this;
  720. var options = self.options;
  721. var ui = self.ui;
  722. //生成月列表
  723. var mArray = [];
  724. if (options.customData.m) {
  725. mArray = options.customData.m;
  726. } else {
  727. for (var m = 1; m <= 12; m++) {
  728. var val = self._fill(m);
  729. mArray.push({
  730. text: val,
  731. value: val
  732. });
  733. }
  734. }
  735. ui.m.picker.setItems(mArray);
  736. //ui.m.picker.setSelectedValue(current);
  737. },
  738. _createDay: function(current) {
  739. var self = this;
  740. var options = self.options;
  741. var ui = self.ui;
  742. //生成日列表
  743. var dArray = [];
  744. if (options.customData.d) {
  745. dArray = options.customData.d;
  746. } else {
  747. var maxDay = self.getDayNum(parseInt(ui.y.picker.getSelectedValue()), parseInt(ui.m.picker.getSelectedValue()));
  748. for (var d = 1; d <= maxDay; d++) {
  749. var val = self._fill(d);
  750. dArray.push({
  751. text: val,
  752. value: val
  753. });
  754. }
  755. }
  756. ui.d.picker.setItems(dArray);
  757. current = current || ui.d.picker.getSelectedValue();
  758. //ui.d.picker.setSelectedValue(current);
  759. },
  760. _createHours: function(current) {
  761. var self = this;
  762. var options = self.options;
  763. var ui = self.ui;
  764. //生成时列表
  765. var hArray = [];
  766. if (options.customData.h) {
  767. hArray = options.customData.h;
  768. } else {
  769. for (var h = 0; h <= 23; h++) {
  770. var val = self._fill(h);
  771. hArray.push({
  772. text: val,
  773. value: val
  774. });
  775. }
  776. }
  777. ui.h.picker.setItems(hArray);
  778. //ui.h.picker.setSelectedValue(current);
  779. },
  780. _createMinutes: function(current) {
  781. var self = this;
  782. var options = self.options;
  783. var ui = self.ui;
  784. //生成分列表
  785. var iArray = [];
  786. if (options.customData.i) {
  787. iArray = options.customData.i;
  788. } else {
  789. for (var i = 0; i <= 59; i++) {
  790. var val = self._fill(i);
  791. iArray.push({
  792. text: val,
  793. value: val
  794. });
  795. }
  796. }
  797. ui.i.picker.setItems(iArray);
  798. //ui.i.picker.setSelectedValue(current);
  799. },
  800. _setLabels: function() {
  801. var self = this;
  802. var options = self.options;
  803. var ui = self.ui;
  804. ui.labels.each(function(i, label) {
  805. label.innerText = options.labels[i];
  806. });
  807. },
  808. _setButtons: function() {
  809. var self = this;
  810. var options = self.options;
  811. var ui = self.ui;
  812. ui.cancel.innerText = options.buttons[0];
  813. ui.ok.innerText = options.buttons[1];
  814. },
  815. _parseValue: function(value) {
  816. var self = this;
  817. var rs = {};
  818. if (value) {
  819. var parts = value.replace(":", "-").replace(" ", "-").split("-");
  820. rs.y = parts[0];
  821. rs.m = parts[1];
  822. rs.d = parts[2];
  823. rs.h = parts[3];
  824. rs.i = parts[4];
  825. } else {
  826. var now = new Date();
  827. rs.y = now.getFullYear();
  828. rs.m = now.getMonth() + 1;
  829. rs.d = now.getDate();
  830. rs.h = now.getHours();
  831. rs.i = now.getMinutes();
  832. }
  833. return rs;
  834. },
  835. _create: function(options) {
  836. var self = this;
  837. options = options || {};
  838. options.labels = options.labels || ['年', '月', '日', '时', '分'];
  839. options.buttons = options.buttons || ['取消', '确定'];
  840. options.type = options.type || 'datetime';
  841. options.customData = options.customData || {};
  842. self.options = options;
  843. var now = new Date();
  844. options.beginYear = options.beginYear || (now.getFullYear() - 5);
  845. options.endYear = options.endYear || (now.getFullYear() + 5);
  846. var ui = self.ui;
  847. //设定label
  848. self._setLabels();
  849. self._setButtons();
  850. //设定类型
  851. ui.picker.setAttribute('data-type', options.type);
  852. //生成
  853. self._createYear();
  854. self._createMonth();
  855. self._createDay();
  856. self._createHours();
  857. self._createMinutes();
  858. //设定默认值
  859. self.setSelectedValue(options.value);
  860. },
  861. //显示
  862. show: function(callback) {
  863. var self = this;
  864. var ui = self.ui;
  865. self.callback = callback || $.noop;
  866. ui.mask.show();
  867. document.body.classList.add($.className('dtpicker-active-for-page'));
  868. ui.picker.classList.add($.className('active'));
  869. //处理物理返回键
  870. self.__back = $.back;
  871. $.back = function() {
  872. self.hide();
  873. };
  874. },
  875. hide: function() {
  876. var self = this;
  877. if (self.disposed) return;
  878. var ui = self.ui;
  879. ui.picker.classList.remove($.className('active'));
  880. ui.mask.close();
  881. document.body.classList.remove($.className('dtpicker-active-for-page'));
  882. //处理物理返回键
  883. $.back=self.__back;
  884. },
  885. dispose: function() {
  886. var self = this;
  887. self.hide();
  888. setTimeout(function() {
  889. self.ui.picker.parentNode.removeChild(self.ui.picker);
  890. for (var name in self) {
  891. self[name] = null;
  892. delete self[name];
  893. };
  894. self.disposed = true;
  895. }, 300);
  896. }
  897. });
  898. })(mui, document);