yvanui.datebox.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. /**
  2. * YvanUI
  3. *
  4. * Copyright (c) 2018 www.yvanui.com. All rights reserved.
  5. * @author luoyifan@qq.com
  6. * @time 2018-12-18 17:16:00
  7. */
  8. (function ($) {
  9. /**
  10. * create date box
  11. */
  12. function createBox(target) {
  13. var state = $.data(target, 'datebox');
  14. var opts = state.options;
  15. $(target).addClass('datebox-f').combo($.extend({}, opts, {
  16. onShowPanel: function () {
  17. bindEvents(this);
  18. setButtons(this);
  19. setCalendar(this);
  20. setValue(this, $(this).datebox('getText'), true);
  21. opts.onShowPanel.call(this);
  22. }
  23. }));
  24. /**
  25. * if the calendar isn't created, create it.
  26. */
  27. if (!state.calendar) {
  28. var panel = $(target).combo('panel').css('overflow', 'hidden');
  29. panel.panel('options').onBeforeDestroy = function () {
  30. var c = $(this).find('.calendar-shared');
  31. if (c.length) {
  32. c.insertBefore(c[0].pholder);
  33. }
  34. };
  35. var cc = $('<div class="datebox-calendar-inner"></div>').prependTo(panel);
  36. if (opts.sharedCalendar) {
  37. var c = $(opts.sharedCalendar);
  38. if (!c[0].pholder) {
  39. c[0].pholder = $('<div class="calendar-pholder" style="display:none"></div>').insertAfter(c);
  40. }
  41. c.addClass('calendar-shared').appendTo(cc);
  42. if (!c.hasClass('calendar')) {
  43. c.calendar();
  44. }
  45. state.calendar = c;
  46. } else {
  47. state.calendar = $('<div></div>').appendTo(cc).calendar();
  48. }
  49. $.extend(state.calendar.calendar('options'), {
  50. fit: true,
  51. border: false,
  52. onSelect: function (date) {
  53. var target = this.target;
  54. var opts = $(target).datebox('options');
  55. opts.onSelect.call(target, date);
  56. setValue(target, opts.formatter.call(target, date));
  57. $(target).combo('hidePanel');
  58. }
  59. });
  60. }
  61. $(target).combo('textbox').parent().addClass('datebox');
  62. $(target).datebox('initValue', opts.value);
  63. function bindEvents(target) {
  64. var opts = $(target).datebox('options');
  65. var panel = $(target).combo('panel');
  66. panel.unbind('.datebox').bind('click.datebox', function (e) {
  67. if ($(e.target).hasClass('datebox-button-a')) {
  68. var index = parseInt($(e.target).attr('datebox-button-index'));
  69. opts.buttons[index].handler.call(e.target, target);
  70. }
  71. });
  72. }
  73. function setButtons(target) {
  74. var panel = $(target).combo('panel');
  75. if (panel.children('div.datebox-button').length) {return;}
  76. var $button = $('<div class="datebox-button"></div>').appendTo(panel);
  77. for (var i = 0; i < opts.buttons.length; i++) {
  78. var btn = opts.buttons[i];
  79. var $t = $('<a class="datebox-button-a" href="javascript:;"></a>').html($.isFunction(btn.text) ? btn.text(target) : btn.text).appendTo($button);
  80. $t.attr('datebox-button-index', i);
  81. }
  82. }
  83. function setCalendar(target) {
  84. var panel = $(target).combo('panel');
  85. var cc = panel.children('div.datebox-calendar-inner');
  86. panel.children()._outerWidth(panel.width());
  87. state.calendar.appendTo(cc);
  88. state.calendar[0].target = target;
  89. if (opts.panelHeight !== 'auto') {
  90. var height = panel.height();
  91. panel.children().not(cc).each(function () {
  92. height -= $(this).outerHeight();
  93. });
  94. cc._outerHeight(height);
  95. }
  96. state.calendar.calendar('resize');
  97. }
  98. }
  99. /**
  100. * called when user inputs some value in text box
  101. */
  102. function doQuery(target, q) {
  103. setValue(target, q, true);
  104. }
  105. /**
  106. * called when user press enter key
  107. */
  108. function doEnter(target) {
  109. var state = $.data(target, 'datebox');
  110. var opts = state.options;
  111. var current = state.calendar.calendar('options').current;
  112. if (current) {
  113. setValue(target, opts.formatter.call(target, current));
  114. $(target).combo('hidePanel');
  115. }
  116. }
  117. function setValue(target, value, remainText) {
  118. var state = $.data(target, 'datebox');
  119. var opts = state.options;
  120. var calendar = state.calendar;
  121. calendar.calendar('moveTo', opts.parser.call(target, value));
  122. if (remainText) {
  123. $(target).combo('setValue', value);
  124. } else {
  125. if (value) {
  126. value = opts.formatter.call(target, calendar.calendar('options').current);
  127. }
  128. $(target).combo('setText', value).combo('setValue', value);
  129. }
  130. }
  131. $.fn.datebox = function (options, param) {
  132. if (typeof options == 'string') {
  133. var method = $.fn.datebox.methods[options];
  134. if (method) {
  135. return method(this, param);
  136. } else {
  137. return this.combo(options, param);
  138. }
  139. }
  140. options = options || {};
  141. return this.each(function () {
  142. var state = $.data(this, 'datebox');
  143. if (state) {
  144. $.extend(state.options, options);
  145. } else {
  146. $.data(this, 'datebox', {
  147. options: $.extend({}, $.fn.datebox.defaults, $.fn.datebox.parseOptions(this), options)
  148. });
  149. }
  150. createBox(this);
  151. });
  152. };
  153. $.fn.datebox.methods = {
  154. options: function (jq) {
  155. var copts = jq.combo('options');
  156. return $.extend($.data(jq[0], 'datebox').options, {
  157. width: copts.width,
  158. height: copts.height,
  159. originalValue: copts.originalValue,
  160. disabled: copts.disabled,
  161. readonly: copts.readonly
  162. });
  163. },
  164. cloneFrom: function (jq, from) {
  165. return jq.each(function () {
  166. $(this).combo('cloneFrom', from);
  167. $.data(this, 'datebox', {
  168. options: $.extend(true, {}, $(from).datebox('options')),
  169. calendar: $(from).datebox('calendar')
  170. });
  171. $(this).addClass('datebox-f');
  172. });
  173. },
  174. calendar: function (jq) { // get the calendar object
  175. return $.data(jq[0], 'datebox').calendar;
  176. },
  177. initValue: function (jq, value) {
  178. return jq.each(function () {
  179. var opts = $(this).datebox('options');
  180. var value = opts.value;
  181. if (value) {
  182. value = opts.formatter.call(this, opts.parser.call(this, value));
  183. }
  184. $(this).combo('initValue', value).combo('setText', value);
  185. });
  186. },
  187. setValue: function (jq, value) {
  188. return jq.each(function () {
  189. setValue(this, value);
  190. });
  191. },
  192. reset: function (jq) {
  193. return jq.each(function () {
  194. var opts = $(this).datebox('options');
  195. $(this).datebox('setValue', opts.originalValue);
  196. });
  197. }
  198. };
  199. $.fn.datebox.parseOptions = function (target) {
  200. return $.extend({}, $.fn.combo.parseOptions(target), $.parser.parseOptions(target, ['sharedCalendar']));
  201. };
  202. $.fn.datebox.defaults = $.extend({}, $.fn.combo.defaults, {
  203. panelWidth: 250,
  204. panelHeight: 'auto',
  205. sharedCalendar: null,
  206. keyHandler: {
  207. up: function (e) {},
  208. down: function (e) {},
  209. left: function (e) {},
  210. right: function (e) {},
  211. enter: function (e) {doEnter(this);},
  212. query: function (q, e) {doQuery(this, q);}
  213. },
  214. currentText: 'Today',
  215. closeText: 'Close',
  216. clearText: '清空',
  217. okText: 'Ok',
  218. buttons: [{
  219. text: function (target) {return $(target).datebox('options').currentText;},
  220. handler: function (target) {
  221. var opts = $(target).datebox('options');
  222. var now = new Date();
  223. var current = new Date(now.getFullYear(), now.getMonth(), now.getDate());
  224. $(target).datebox('calendar').calendar({
  225. year: current.getFullYear(),
  226. month: current.getMonth() + 1,
  227. current: current
  228. });
  229. opts.onSelect.call(target, current);
  230. doEnter(target);
  231. }
  232. }, {
  233. text: function (target) {return $(target).datebox('options').clearText;},
  234. handler: function (target) {
  235. $(target).datebox('clear');
  236. $(this).closest('div.combo-panel').panel('close');
  237. }
  238. }, {
  239. text: function (target) {return $(target).datebox('options').closeText;},
  240. handler: function (target) {
  241. $(this).closest('div.combo-panel').panel('close');
  242. }
  243. }],
  244. formatter: function (date) {
  245. var y = date.getFullYear();
  246. var m = date.getMonth() + 1;
  247. var d = date.getDate();
  248. return (m < 10 ? ('0' + m) : m) + '/' + (d < 10 ? ('0' + d) : d) + '/' + y;
  249. },
  250. parser: function (s) {
  251. if (!s) return new Date();
  252. var ss = s.split('/');
  253. var m = parseInt(ss[0], 10);
  254. var d = parseInt(ss[1], 10);
  255. var y = parseInt(ss[2], 10);
  256. if (!isNaN(y) && !isNaN(m) && !isNaN(d)) {
  257. return new Date(y, m - 1, d);
  258. } else {
  259. return new Date();
  260. }
  261. },
  262. onSelect: function (date) {}
  263. });
  264. })(jQuery);