Calendar.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. MWF.xDesktop.requireApp("process.Xform", "$Input", null, false);
  2. /** @class Calendar 日期组件。
  3. * @o2cn 日期选择
  4. * @example
  5. * //可以在脚本中获取该组件
  6. * //方法1:
  7. * var field = this.form.get("fieldId"); //获取组件对象
  8. * //方法2
  9. * var field = this.target; //在组件本身的脚本中获取,比如事件脚本、默认值脚本、校验脚本等等
  10. * @extends MWF.xApplication.process.Xform.$Input
  11. * @o2category FormComponents
  12. * @o2range {Process|CMS|Portal}
  13. * @hideconstructor
  14. */
  15. MWF.xApplication.process.Xform.Calendar = MWF.APPCalendar = new Class(
  16. /** @lends MWF.xApplication.process.Xform.Calendar# */
  17. {
  18. Implements: [Events],
  19. Extends: MWF.APP$Input,
  20. iconStyle: "calendarIcon",
  21. options: {
  22. /**
  23. * 日期选择完成时触发.
  24. * @event MWF.xApplication.process.Xform.Calendar#complete
  25. * @see {@link https://www.yuque.com/o2oa/ixsnyt/hm5uft#i0zTS|组件事件说明}
  26. */
  27. /**
  28. * 日期选择器上点清空时触发.
  29. * @event MWF.xApplication.process.Xform.Calendar#clear
  30. * @see {@link https://www.yuque.com/o2oa/ixsnyt/hm5uft#i0zTS|组件事件说明}
  31. */
  32. /**
  33. * 值改变时触发.
  34. * @event MWF.xApplication.process.Xform.Calendar#change
  35. * @see {@link https://www.yuque.com/o2oa/ixsnyt/hm5uft#i0zTS|组件事件说明}
  36. */
  37. /**
  38. * 显示日期选择器时触发.
  39. * @event MWF.xApplication.process.Xform.Calendar#show
  40. * @see {@link https://www.yuque.com/o2oa/ixsnyt/hm5uft#i0zTS|组件事件说明}
  41. */
  42. /**
  43. * 隐藏日期选择器时触发.
  44. * @event MWF.xApplication.process.Xform.Calendar#hide
  45. * @see {@link https://www.yuque.com/o2oa/ixsnyt/hm5uft#i0zTS|组件事件说明}
  46. */
  47. "moduleEvents": ["queryLoad","postLoad","load","complete", "clear", "change","show","hide"]
  48. },
  49. _loadNode: function(){
  50. if (this.isReadonly()){
  51. this._loadNodeRead();
  52. }else{
  53. this._loadNodeEdit();
  54. var input = this.node.getFirst();
  55. input.set("readonly", true);
  56. }
  57. },
  58. setDescriptionEvent: function(){
  59. if (this.descriptionNode){
  60. this.descriptionNode.addEvents({
  61. "mousedown": function(){
  62. this.descriptionNode.setStyle("display", "none");
  63. //this.clickSelect();
  64. }.bind(this)
  65. });
  66. }
  67. },
  68. // getData: function(when){
  69. // if (this.json.compute == "save") this._setValue(this._computeValue());
  70. // return this.getInputData();
  71. // },
  72. getInputData: function(){
  73. if (typeOf(this.tmpDateString) === 'string'){
  74. return this.tmpDateString;
  75. }else{
  76. return this._getBusinessData();
  77. }
  78. },
  79. _getValueAg: function(value,isDate){
  80. if (value && value.isAG){
  81. return value.then(function(v){
  82. this._getValueAg(v, isDate);
  83. }.bind(this), function(){});
  84. }else{
  85. var d = (!!value) ? Date.parse(value) : "";
  86. if (isDate){
  87. return d || null;
  88. }else{
  89. return (d) ? d.format(this.json.format) : "";
  90. }
  91. }
  92. },
  93. resetData: function(){
  94. this.setData(this.getValue());
  95. },
  96. /**
  97. * @summary 获取显示的值,或格式化后的文本。
  98. * @return {String} 获取显示的值,或格式化后的文本
  99. * @example
  100. * var text = this.form.get('fieldId').getText(); //获取选中项的文本
  101. */
  102. getText: function (){
  103. if( this.node.getFirst() ){
  104. return this.node.getFirst().get("value");
  105. }else{
  106. var value = this._getBusinessData();
  107. var date = this.toDate(value);
  108. return date ? date.format(this.json.format) : value;
  109. }
  110. },
  111. getValue: function(isDate){
  112. if (this.moduleValueAG) return this.moduleValueAG;
  113. var value = this._getBusinessData();
  114. if( value && !isDate)return value;
  115. if (!value) value = this._computeValue();
  116. if (value && value.then) return value;
  117. var d = (!!value) ? Date.parse(value) : "";
  118. if (isDate){
  119. return d || null;
  120. }else{
  121. //if (d) value = Date.parse(value).format(this.json.format);
  122. return (d) ? d.format( this.json.valueFormat || this.json.format) : "";
  123. }
  124. return value || "";
  125. },
  126. getValueStr: function(){
  127. var value = this._getBusinessData();
  128. if (!value) value = this._computeValue();
  129. return value;
  130. },
  131. __setData: function(data, fireChange){
  132. var old = this._getBusinessData();
  133. var date = this.toDate(data);
  134. var val = (date && this.json.valueFormat) ? date.format(this.json.valueFormat) : data;
  135. var text = date ? date.format(this.json.format) : data;
  136. this._setBusinessData(val);
  137. if (this.node.getFirst()){
  138. this.node.getFirst().set("value", text);
  139. this.checkDescription();
  140. this.validationMode();
  141. }else{
  142. this.node.set("text", text);
  143. }
  144. if (fireChange && old!==val) this.fireEvent("change");
  145. this.moduleValueAG = null;
  146. },
  147. __setValue: function(value){
  148. var date = this.toDate(value);
  149. var val = date ? date.format(this.json.valueFormat || this.json.format) : value;
  150. var text = date ? date.format(this.json.format) : value;
  151. this._setBusinessData(val);
  152. if (this.node.getFirst()) this.node.getFirst().set("value", text || "");
  153. if (this.isReadonly()) this.node.set("text", text);
  154. this.moduleValueAG = null;
  155. this.fieldModuleLoaded = true;
  156. return value;
  157. },
  158. _beforeReloaded: function(){
  159. this.calendar = null;
  160. },
  161. clickSelect: function(){
  162. var _self = this;
  163. if (!this.calendar){
  164. MWF.require("MWF.widget.Calendar", function(){
  165. var defaultView = "day";
  166. if( this.json.selectType === "month" )defaultView = "month";
  167. if( this.json.selectType === "year" )defaultView = "year";
  168. var options = {
  169. "style": o2.session.isMobile ? "xform_mobile" : "xform",
  170. "secondEnable" : this.json.isSelectSecond,
  171. "timeSelectType" : this.json.timeSelectType,
  172. "isTime": (this.json.selectType==="datetime" || this.json.selectType==="time"),
  173. "timeOnly": (this.json.selectType === "time"),
  174. "monthOnly" : (this.json.selectType === "month"),
  175. "yearOnly" : (this.json.selectType === "year"),
  176. "defaultView" : defaultView,
  177. //"target": this.form.node,
  178. "target": o2.session.isMobile ? $(document.body) : this.form.app.content,
  179. "format": this.json.format,
  180. "onComplate": function(formatedDate, date){
  181. this.tmpDateString = date.format( this.json.valueFormat || this.json.format );
  182. this.validationMode();
  183. if(this.validation()){
  184. var v = this.getInputData("change");
  185. this._setBusinessData(v);
  186. this.tmpDateString = null;
  187. //this._setEnvironmentData(v);
  188. }
  189. this.fireEvent("complete");
  190. }.bind(this),
  191. "onChange": function(formatedDate, date){
  192. this.tmpDateString = date ? date.format( this.json.valueFormat || this.json.format ) : "";
  193. this._setBusinessData(this.getInputData("change"));
  194. this.tmpDateString = null;
  195. this.fireEvent("change");
  196. }.bind(this),
  197. "onClear": function(){
  198. this.validationMode();
  199. if(this.validation()){
  200. this.tmpDateString = "";
  201. var v = this.getInputData("change");
  202. this._setBusinessData(v);
  203. this.tmpDateString = null;
  204. //this._setEnvironmentData(v);
  205. }
  206. this.fireEvent("clear");
  207. if (!this.node.getFirst().get("value")) if (this.descriptionNode) this.descriptionNode.setStyle("display", "block");
  208. }.bind(this),
  209. "onShow": function(){
  210. if (_self.descriptionNode) _self.descriptionNode.setStyle("display", "none");
  211. if( o2.session.isMobile ){
  212. this.container.position({
  213. relativeTo: $(document.body),
  214. position: 'leftCenter',
  215. edge: 'leftCenter'
  216. //offset : { y : -25 }
  217. });
  218. }else{
  219. var parent = _self.node.getParent();
  220. while( parent ){
  221. var overflow = parent.getStyle("overflow");
  222. var overflowY = parent.getStyle("overflow-y");
  223. if( overflow === "auto" || overflow === "scroll" || overflowY === "auto" || overflowY === "scroll" ){
  224. _self.scrollFun = function( e ){
  225. // if (this.container.position && (!layout || !layout.userLayout || !layout.userLayout.scale || layout.userLayout.scale===1) ){
  226. if( this.postX === "right" ){
  227. if( this.postY === "bottom" ){
  228. this.container.position({
  229. relativeTo: this.node,
  230. position: 'bottomRight',
  231. edge: 'upperRight',
  232. allowNegative : true
  233. });
  234. }else{
  235. this.container.position({
  236. relativeTo: this.node,
  237. position: 'upperRight',
  238. edge: 'bottomRight',
  239. allowNegative : true
  240. });
  241. }
  242. }else{
  243. if( this.postY === "bottom" ) {
  244. this.container.position({
  245. relativeTo: this.node,
  246. position: 'bottomLeft',
  247. edge: 'upperLeft',
  248. allowNegative: true
  249. });
  250. }else{
  251. this.container.position({
  252. relativeTo: this.node,
  253. position: 'upperLeft',
  254. edge: 'bottomLeft',
  255. allowNegative: true
  256. });
  257. }
  258. }
  259. // }else{
  260. // var p = this.node.getPosition(this.options.target || null);
  261. // var size = this.node.getSize();
  262. // var containerSize = this.container.getSize();
  263. // var bodySize = (this.options.target) ? this.options.target.getSize() : $(document.body).getSize(); //$(document.body).getSize();
  264. //
  265. // bodySize.x = bodySize.x * layout.userLayout.scale;
  266. // bodySize.y = bodySize.y * layout.userLayout.scale;
  267. //
  268. // var left = p.x;
  269. // left = left * layout.userLayout.scale;
  270. // if ((left + containerSize.x + 40) > bodySize.x){
  271. // left = bodySize.x - containerSize.x - 40;
  272. // }
  273. //
  274. // var top = p.y+size.y+2;
  275. // top = top * layout.userLayout.scale;
  276. // if( top + containerSize.y > bodySize.y ){
  277. // top = bodySize.y - containerSize.y ;
  278. // }
  279. //
  280. // this.container.setStyle("top", top);
  281. // this.container.setStyle("left", left);
  282. // }
  283. }.bind(this);
  284. _self.scrollParentNode = parent;
  285. parent.addEvent( "scroll", _self.scrollFun );
  286. parent = null;
  287. }else{
  288. parent = parent.getParent();
  289. }
  290. }
  291. }
  292. _self.fireEvent("show");
  293. },
  294. "onHide": function(){
  295. if (!this.node.getFirst().get("value")) if (this.descriptionNode) this.descriptionNode.setStyle("display", "block");
  296. if( _self.scrollParentNode && _self.scrollFun ){
  297. _self.scrollParentNode.removeEvent("scroll", _self.scrollFun);
  298. }
  299. _self.fireEvent("hide");
  300. }.bind(this)
  301. };
  302. options.baseDate = this.getBaseDate();
  303. this.setRange( options );
  304. /**
  305. * @summary 日期弹出选择界面,只读情况下无此成员.
  306. * @member {MWF.widget.Calendar}
  307. * @example
  308. * var calendar = this.form.get("fieldId").calendar; //获取组件
  309. * if(calendar)calendar.show(); //弹出选择组件
  310. */
  311. this.calendar = new MWF.widget.Calendar(this.node.getFirst(), options);
  312. if( this.form.json && this.form.json.canlendarStyle && typeOf( this.form.json.canlendarStyle.zIndex ) !== "null" && typeOf( this.form.json.canlendarStyle.zIndex ) !== "undefined" ){
  313. this.calendar.container.setStyle("z-index", this.form.json.canlendarStyle.zIndex );
  314. }
  315. this.calendar.show();
  316. }.bind(this));
  317. }else{
  318. var options = {};
  319. options.baseDate = this.getBaseDate();
  320. this.calendar.setOptions(options);
  321. //this.calendar.show();
  322. this.node.getFirst().focus();
  323. }
  324. },
  325. getBaseDate : function(){
  326. var d;
  327. var value = this.getValue(true);
  328. if( value && value.getTime() > 10000 ){
  329. d = value;
  330. }else{
  331. var ud = Date.parse( this.unformatDate( this.getValueStr() ) );
  332. if( ud && ud.getTime() > 10000 ){
  333. d = ud;
  334. }else{
  335. d = new Date();
  336. }
  337. }
  338. return d;
  339. },
  340. setRange: function( options ){
  341. var r;
  342. switch ( this.json.rangeType ) {
  343. case "dateTime":
  344. if (this.json.dateTimeRangeScript && this.json.dateTimeRangeScript.code) {
  345. r = this.form.Macro.fire(this.json.dateTimeRangeScript.code, this);
  346. if (typeOf(r) === "array") options.datetimeRange = r;
  347. }
  348. break;
  349. case "dateAndTime":
  350. if (this.json.dateRangeScript && this.json.dateRangeScript.code) {
  351. r = this.form.Macro.fire(this.json.dateRangeScript.code, this);
  352. if (typeOf(r) === "array") options.dateRange = r;
  353. }
  354. if (this.json.timeRangeScript && this.json.timeRangeScript.code) {
  355. r = this.form.Macro.fire(this.json.timeRangeScript.code, this);
  356. if (typeOf(r) === "array") options.timeRange = r;
  357. }
  358. break;
  359. case "other":
  360. if (this.json.enableDate && this.json.enableDate.code) {
  361. options.enableDate = function (date) {
  362. var d = this.getPureDate( date );
  363. return this.form.Macro.fire(this.json.enableDate.code, this, {date: d});
  364. }.bind(this);
  365. }
  366. if (this.json.enableHours && this.json.enableHours.code) {
  367. options.enableHours = function (date) {
  368. var d = this.getPureDate( date );
  369. return this.form.Macro.fire(this.json.enableHours.code, this, {date: d});
  370. }.bind(this);
  371. }
  372. if (this.json.enableMinutes && this.json.enableMinutes.code) {
  373. options.enableMinutes = function (date, hour) {
  374. var d = this.getPureDate( date );
  375. return this.form.Macro.fire(this.json.enableMinutes.code, this, {date: d, hour: hour.toInt()});
  376. }.bind(this);
  377. }
  378. if (this.json.enableSeconds && this.json.enableSeconds.code) {
  379. options.enableSeconds = function (date, hour, minute) {
  380. var d = this.getPureDate( date );
  381. return this.form.Macro.fire(this.json.enableSeconds.code, this, {date: d, hour: hour.toInt(), minute: minute.toInt()});
  382. }.bind(this);
  383. }
  384. break;
  385. }
  386. },
  387. toDate: function( value ){
  388. if( !value )return null;
  389. switch (typeOf(value)) {
  390. case "string": return (new Date(value) === "Invalid Date") ? null : Date.parse(value);
  391. case "date": return value;
  392. default: return null;
  393. }
  394. },
  395. getPureDate: function (date) {
  396. var d;
  397. switch (typeOf(date)) {
  398. case "string": d = Date.parse(date); break;
  399. case "date": d = date.clone(); break;
  400. default: return null;
  401. }
  402. return d.clearTime();
  403. },
  404. unformatDate : function( dateStr ){
  405. var formatStr = this.json.valueFormat || this.json.format;
  406. var matchArr = [ "%Y", "%m", "%d", "%H", "%M", "%S", "%z", "%Z" ];
  407. var lengthArr = [ 4, 2, 2, 2, 2, 2, 5, 3];
  408. var indexArr = [ formatStr.indexOf("%Y"), formatStr.indexOf("%m"), formatStr.indexOf("%d"), formatStr.indexOf("%H"), formatStr.indexOf("%M"), formatStr.indexOf("%S"), formatStr.indexOf("%z"), formatStr.indexOf("%Z") ];
  409. var resultArr = [ null, null, null, null, null, null, null, null ];
  410. for( var i=0; i<matchArr.length; i++ ){
  411. if( indexArr[i] === -1 )continue;
  412. var leftLength = 0;
  413. var leftUnitLength = 0;
  414. Array.each( indexArr, function( n, k ){
  415. if( n === -1 )return;
  416. if( indexArr[i] > n ){
  417. leftLength += lengthArr[k];
  418. leftUnitLength += matchArr[k].length;
  419. }
  420. });
  421. resultArr[i] = dateStr.substr( indexArr[i] - leftUnitLength + leftLength, lengthArr[i] );
  422. }
  423. var now = new Date();
  424. for( var i=0; i < resultArr.length; i++ ){
  425. if( !resultArr[i] ){
  426. switch ( matchArr[i] ){
  427. case "%Y":
  428. case "%m":
  429. case "%d":
  430. resultArr[i] = now.format( matchArr[i] );
  431. break;
  432. case "%H":
  433. case "%M":
  434. case "%S":
  435. resultArr[i] = "00";
  436. break;
  437. case "%z":
  438. case "%Z":
  439. default:
  440. break;
  441. }
  442. }
  443. }
  444. return resultArr[0] + "-" + resultArr[1] + "-" + resultArr[2] + " " + resultArr[3]+":"+resultArr[4]+":"+resultArr[5];
  445. },
  446. getExcelData: function(){
  447. return this.getData();
  448. },
  449. setExcelData: function(d){
  450. var value = d.replace(/&#10;/g,""); //换行符&#10;
  451. this.excelData = value;
  452. var json = this.json;
  453. if( value && (new Date(value).isValid()) ){
  454. var format;
  455. if (!json.format){
  456. if (json.selectType==="datetime" || json.selectType==="time"){
  457. format = (json.selectType === "time") ? "%H:%M" : (Locale.get("Date").shortDate + " " + "%H:%M")
  458. }else{
  459. format = Locale.get("Date").shortDate;
  460. }
  461. }else{
  462. format = json.format;
  463. }
  464. value = Date.parse( value ).format( format );
  465. this.setData(value, true);
  466. }else{
  467. this.setData(value, true);
  468. }
  469. }
  470. });