Checkbox.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  1. MWF.xDesktop.requireApp("process.Xform", "$Selector", null, false);
  2. MWF.require("MWF.widget.UUID", null, false);
  3. /** @class Calendar 多选按钮组件。
  4. * @o2cn 多选按钮
  5. * @example
  6. * //可以在脚本中获取该组件
  7. * //方法1:
  8. * var field = this.form.get("fieldId"); //获取组件对象
  9. * //方法2
  10. * var field = this.target; //在组件本身的脚本中获取,比如事件脚本、默认值脚本、校验脚本等等
  11. * @extends MWF.xApplication.process.Xform.$Selector
  12. * @o2category FormComponents
  13. * @o2range {Process|CMS|Portal}
  14. * @hideconstructor
  15. */
  16. MWF.xApplication.process.Xform.Checkbox = MWF.APPCheckbox = new Class(
  17. /** @lends MWF.xApplication.process.Xform.Checkbox# */
  18. {
  19. Implements: [Events],
  20. Extends: MWF.APP$Selector,
  21. /**
  22. * 组件加载后触发。如果选项加载为异步,则异步处理完成后触发此事件
  23. * @event MWF.xApplication.process.Xform.Checkbox#load
  24. * @see {@link https://www.yuque.com/o2oa/ixsnyt/hm5uft#i0zTS|组件事件说明}
  25. */
  26. /**
  27. * 值改变时触发。可以通过this.event获取修改后的选择项(Dom对象)。
  28. * @event MWF.xApplication.process.Xform.Checkbox#change
  29. * @see {@link https://www.yuque.com/o2oa/ixsnyt/hm5uft#i0zTS|组件事件说明}
  30. */
  31. loadDescription: function(){},
  32. _loadNode: function(){
  33. if (this.isReadonly()){
  34. this._loadNodeRead();
  35. }else{
  36. this._loadNodeEdit();
  37. }
  38. },
  39. _loadMergeReadContentNode: function( contentNode, data ){
  40. this._showValue(contentNode, data.data)
  41. },
  42. _loadMergeEditNodeByDefault: function(){
  43. var data = this.getSortedSectionData();
  44. var businessData = [];
  45. data.each(function(d){
  46. businessData = businessData.concat( d.data || [] );
  47. });
  48. this._setBusinessData( businessData );
  49. this._loadNode();
  50. },
  51. _loadNodeRead: function(){
  52. this.node.empty();
  53. this.node.set({
  54. "nodeId": this.json.id,
  55. "MWFType": this.json.type
  56. });
  57. var value = this.getValue();
  58. this._showValue(this.node, value)
  59. },
  60. __showValue: function(node, value, optionItems){
  61. if( !value )return;
  62. var texts = [];
  63. optionItems.each(function(item){
  64. var tmps = item.split("|");
  65. var t = tmps[0];
  66. var v = tmps[1] || t;
  67. if (value.indexOf(v)!=-1){
  68. texts.push(t);
  69. }
  70. });
  71. if( !this.isNumber(this.json.countPerline) ) {
  72. if( this.json.newline ){
  73. texts.each(function(t){
  74. new Element("div", { "text": t }).inject(node)
  75. }.bind(this))
  76. }else{
  77. node.set("text", texts.join(", "));
  78. }
  79. }else{
  80. var div;
  81. var countPerLine = this.json.countPerline.toInt();
  82. if( countPerLine === 0 ){
  83. div = new Element("div", {"style":"display:inline-block;"}).inject( node );
  84. div.set("text", texts.join(", "));
  85. }else{
  86. var textsPerLine = [];
  87. texts.each(function(t, i){
  88. if( i % countPerLine === 0){ //如果需要换行了
  89. if( div && textsPerLine.length )div.set("text", textsPerLine.join(",") +",");
  90. textsPerLine = [];
  91. div = new Element("div").inject( node );
  92. }
  93. textsPerLine.push( t );
  94. }.bind(this));
  95. if( div && textsPerLine.length )div.set("text", textsPerLine.join(","));
  96. }
  97. }
  98. },
  99. _resetNodeEdit: function(){
  100. var div = new Element("div");
  101. div.set(this.json.properties);
  102. div.inject(this.node, "after");
  103. this.node.destroy();
  104. this.node = div;
  105. },
  106. _loadNodeEdit: function(){
  107. //this.container = new Element("select");
  108. if (!this.json.preprocessing) this._resetNodeEdit();
  109. this.node.set({
  110. "id": this.json.id,
  111. "MWFType": this.json.type,
  112. "styles": {
  113. "display": "inline"
  114. }
  115. });
  116. if( this.json.newline )this.node.setStyle("display", "block");
  117. this.setOptions();
  118. },
  119. _loadDomEvents: function(){
  120. },
  121. _loadEvents: function(){
  122. Object.each(this.json.events, function(e, key){
  123. if (e.code){
  124. if (this.options.moduleEvents.indexOf(key)!=-1){
  125. this.addEvent(key, function(event){
  126. return this.form.Macro.fire(e.code, this, event);
  127. }.bind(this));
  128. }else{
  129. //this.node.addEvent(key, function(event){
  130. // return this.form.Macro.fire(e.code, this, event);
  131. //}.bind(this));
  132. }
  133. }
  134. }.bind(this));
  135. },
  136. addModuleEvent: function(key, fun){
  137. if (this.options.moduleEvents.indexOf(key)!==-1){
  138. this.addEvent(key, function(event){
  139. return (fun) ? fun(this, event) : null;
  140. }.bind(this));
  141. }else{
  142. var inputs = this.node.getElements("input");
  143. inputs.each(function(input){
  144. input.addEvent(key, function(event){
  145. return (fun) ? fun(this, event) : null;
  146. }.bind(this));
  147. }.bind(this));
  148. }
  149. },
  150. isNumber : function( d ){
  151. return parseInt(d).toString() !== "NaN";
  152. },
  153. _setOptions: function(optionItems){
  154. var p = o2.promiseAll(optionItems).then(function(radioValues){
  155. this.moduleSelectAG = null;
  156. if (!radioValues) radioValues = [];
  157. var node;
  158. if (o2.typeOf(radioValues)==="array"){
  159. var flag = (new MWF.widget.UUID).toString();
  160. radioValues.each(function(item, i){
  161. var tmps = item.split("|");
  162. var text = tmps[0];
  163. var value = tmps[1] || text;
  164. if( !this.isNumber(this.json.countPerline) ) {
  165. if( this.json.newline ){
  166. node = new Element("div").inject(this.node);
  167. }else{
  168. node = this.node;
  169. }
  170. }else{
  171. var countPerLine = this.json.countPerline.toInt();
  172. if( countPerLine === 0 ){
  173. if(i===0)node = new Element("div", {"style":"display:inline-block;"}).inject(this.node);
  174. }else if( i % countPerLine === 0){
  175. node = new Element("div").inject(this.node);
  176. }
  177. }
  178. var radio = new Element("input", {
  179. "type": "checkbox",
  180. "name": ((this.json.properties) ? this.json.properties.name : null) || flag+this.json.id,
  181. "value": value,
  182. "showText": text,
  183. "styles": this.json.buttonStyles
  184. }).inject(node);
  185. //radio.appendText(text, "after");
  186. var textNode = new Element( "span", {
  187. "text" : text,
  188. "styles" : { "cursor" : "default" }
  189. }).inject(node);
  190. textNode.addEvent("click", function( ev ){
  191. if( this.radio.get("disabled") === true || this.radio.get("disabled") === "true" )return;
  192. this.radio.checked = ! this.radio.checked;
  193. this.radio.fireEvent("change", [this.radio]);
  194. this.radio.fireEvent("click");
  195. }.bind( {radio : radio} ) );
  196. radio.addEvent("click", function(){
  197. this.validationMode();
  198. if (this.validation()) {
  199. var v = this.getInputData("change");
  200. this._setBusinessData(v || []);
  201. //this._setEnvironmentData(v || []);
  202. //this._setBusinessData(this.getInputData("change") || []);
  203. this.fireEvent("change", [radio]);
  204. }
  205. }.bind(this));
  206. Object.each(this.json.events, function(e, key){
  207. if (e.code){
  208. if (this.options.moduleEvents.indexOf(key)!=-1){
  209. }else{
  210. radio.addEvent(key, function(event){
  211. return this.form.Macro.fire(e.code, this, event);
  212. }.bind(this));
  213. }
  214. }
  215. }.bind(this));
  216. }.bind(this));
  217. }
  218. }.bind(this), function(){});
  219. this.moduleSelectAG = p;
  220. if (p) p.then(function(){
  221. this.moduleSelectAG = null;
  222. }.bind(this), function(){
  223. this.moduleSelectAG = null;
  224. }.bind(this));
  225. },
  226. _setValue: function(value, m, fireChange){
  227. var mothed = m || "__setValue";
  228. if (!!value){
  229. var p = o2.promiseAll(value).then(function(v){
  230. //if (o2.typeOf(v)=="array") v = v[0];
  231. if (this.moduleSelectAG){
  232. this.moduleValueAG = this.moduleSelectAG;
  233. this.moduleSelectAG.then(function(){
  234. this[mothed](v, fireChange);
  235. return v;
  236. }.bind(this), function(){});
  237. }else{
  238. this[mothed](v, fireChange)
  239. }
  240. return v;
  241. }.bind(this), function(){});
  242. this.moduleValueAG = p;
  243. if (this.moduleValueAG) this.moduleValueAG.then(function(){
  244. this.moduleValueAG = null;
  245. }.bind(this), function(){
  246. this.moduleValueAG = null;
  247. }.bind(this));
  248. }else{
  249. this[mothed](value, fireChange);
  250. }
  251. // this.moduleValueAG = o2.AG.all(value).then(function(v){
  252. // if (this.moduleSelectAG){
  253. // this.moduleValueAG = this.moduleSelectAG;
  254. // this.moduleSelectAG.then(function(){
  255. // this.moduleValueAG = null;
  256. // this.__setValue(v);
  257. // }.bind(this));
  258. // }else{
  259. // this.moduleValueAG = null;
  260. // this.__setValue(v);
  261. // }
  262. // return v;
  263. // }.bind(this));
  264. //
  265. // if (this.moduleValueAG) this.moduleValueAG.then(function(){
  266. // this.moduleValueAG = "";
  267. // }.bind(this));
  268. },
  269. __setValue: function(value){
  270. this.moduleValueAG = null;
  271. this._setBusinessData(value);
  272. if (this.isReadonly()){
  273. this._loadNodeRead();
  274. }else{
  275. var radios = this.node.getElements("input");
  276. for (var i=0; i<radios.length; i++){
  277. var radio = radios[i];
  278. radio.checked = value.indexOf(radio.value) != -1;
  279. }
  280. }
  281. this.fieldModuleLoaded = true;
  282. },
  283. _getInputTextData: function(){
  284. var inputs = this.node.getElements("input");
  285. var value = [];
  286. var text = [];
  287. if (inputs.length){
  288. inputs.each(function(input){
  289. if (input.checked){
  290. var v = input.get("value");
  291. var t = input.get("showText");
  292. value.push(v || "");
  293. text.push(t || v || "");
  294. }
  295. });
  296. }
  297. if (!value.length) value = [""];
  298. if (!text.length) text = [""];
  299. return {"value": value, "text": text};
  300. },
  301. /**
  302. * @summary 获取选中项的text,如果未选中返回空数组。
  303. * @return {Array} 返回选中项的text数组
  304. * @example
  305. * var array = this.form.get('fieldId').getText(); //获取选中项的数组
  306. */
  307. getText: function(){
  308. var texts = this.getTextData().text;
  309. if( texts && texts.length === 1 ){
  310. return texts[0] ? texts : [];
  311. }else{
  312. return (texts && texts.length) ? texts : [];
  313. }
  314. },
  315. //getData: function(){
  316. //var inputs = this.node.getElements("input");
  317. //var value = [];
  318. //if (inputs.length){
  319. // inputs.each(function(input){
  320. // if (input.checked){
  321. // var v = input.get("value");
  322. // if (v) value.push(v || "");
  323. // }
  324. // });
  325. //}
  326. //return (value.length==1) ? value[0] : value;
  327. //},
  328. isEmpty: function(){
  329. var data = this.getData();
  330. if( typeOf(data) !== "array" )return true;
  331. if( data.length === 0 )return true;
  332. return false;
  333. },
  334. getInputData: function(){
  335. if (this.isReadonly()){
  336. return this._getBusinessData();
  337. }else{
  338. var inputs = this.node.getElements("input");
  339. var value = [];
  340. if (inputs.length){
  341. inputs.each(function(input){
  342. if (input.checked){
  343. var v = input.get("value");
  344. value.push(v || "");
  345. }
  346. });
  347. }
  348. return (value.length) ? value : [];
  349. }
  350. },
  351. resetData: function(){
  352. this.setData(this.getValue());
  353. },
  354. /**当参数为Promise的时候,请查看文档: {@link https://www.yuque.com/o2oa/ixsnyt/ws07m0|使用Promise处理表单异步}
  355. * @summary 为字段赋值,并且使值对应的选项选中。
  356. * @param data{String|Promise} .
  357. * @param fireChange{boolean} 可选,是否触发change事件,默认false.
  358. * @example
  359. * this.form.get("fieldId").setData("test"); //赋文本值
  360. * @example
  361. * //使用Promise
  362. * var field = this.form.get("fieldId");
  363. * var dict = new this.Dict("test"); //test为数据字典名称
  364. * var promise = dict.get("tools", true); //异步使用数据字典的get方法时返回Promise,参数true表示异步
  365. * field.setData( promise );
  366. */
  367. setData: function(data, fireChange){
  368. return this._setValue(data, "__setData", fireChange);
  369. // if (data && data.isAG){
  370. // this.moduleValueAG = data;
  371. // data.addResolve(function(v){
  372. // this.setData(v);
  373. // }.bind(this));
  374. // }else{
  375. // this.__setData(data);
  376. // this.moduleValueAG = null;
  377. // }
  378. },
  379. __setData: function(data, fireChange){
  380. this.moduleValueAG = null;
  381. var old = this.getInputData();
  382. this._setBusinessData(data);
  383. var inputs = this.node.getElements("input");
  384. if (inputs.length){
  385. inputs.each(function(input){
  386. if (typeOf(data)=="array"){
  387. if (data.indexOf(input.get("value"))!=-1){
  388. input.set("checked", true);
  389. }else{
  390. input.set("checked", false);
  391. }
  392. }else{
  393. if (data == input.get("value")){
  394. input.set("checked", true);
  395. }else{
  396. input.set("checked", false);
  397. }
  398. }
  399. });
  400. this.validationMode();
  401. }
  402. this.fieldModuleLoaded = true;
  403. this.fireEvent("setData");
  404. if (fireChange && old!==data) this.fireEvent("change");
  405. },
  406. notValidationMode: function(text){
  407. if (!this.isNotValidationMode){
  408. this.isNotValidationMode = true;
  409. this.node.store("background", this.node.getStyles("background"));
  410. this.node.setStyle("background", "#ffdcdc");
  411. this.errNode = this.createErrorNode(text);
  412. if (this.iconNode){
  413. this.errNode.inject(this.iconNode, "after");
  414. }else{
  415. this.errNode.inject(this.node, "after");
  416. }
  417. this.showNotValidationMode(this.node);
  418. if (!this.errNode.isIntoView()) this.errNode.scrollIntoView(false);
  419. }
  420. },
  421. validationMode: function(){
  422. if (this.isNotValidationMode){
  423. this.isNotValidationMode = false;
  424. this.node.setStyles(this.node.retrieve("background"));
  425. if (this.errNode){
  426. this.errNode.destroy();
  427. this.errNode = null;
  428. }
  429. }
  430. },
  431. validationConfigItem: function(routeName, data){
  432. var flag = (data.status==="all") ? true: (routeName === data.decision);
  433. if (flag){
  434. var n = this.getInputData();
  435. if( typeOf(n)==="array" && n.length === 0 )n = "";
  436. var v = (data.valueType==="value") ? n : n.length;
  437. switch (data.operateor){
  438. case "isnull":
  439. if (!v){
  440. this.notValidationMode(data.prompt);
  441. return false;
  442. }
  443. break;
  444. case "notnull":
  445. if (v){
  446. this.notValidationMode(data.prompt);
  447. return false;
  448. }
  449. break;
  450. case "gt":
  451. if (v>data.value){
  452. this.notValidationMode(data.prompt);
  453. return false;
  454. }
  455. break;
  456. case "lt":
  457. if (v<data.value){
  458. this.notValidationMode(data.prompt);
  459. return false;
  460. }
  461. break;
  462. case "equal":
  463. if (v==data.value){
  464. this.notValidationMode(data.prompt);
  465. return false;
  466. }
  467. break;
  468. case "neq":
  469. if (v!=data.value){
  470. this.notValidationMode(data.prompt);
  471. return false;
  472. }
  473. break;
  474. case "contain":
  475. if (v.indexOf(data.value)!=-1){
  476. this.notValidationMode(data.prompt);
  477. return false;
  478. }
  479. break;
  480. case "notcontain":
  481. if (v.indexOf(data.value)==-1){
  482. this.notValidationMode(data.prompt);
  483. return false;
  484. }
  485. break;
  486. }
  487. }
  488. return true;
  489. },
  490. getExcelData: function( type ){
  491. var value = this.getData();
  492. if( type === "value" )return value;
  493. var options = this.getOptionsObj();
  494. return Promise.resolve(options).then(function (opts) {
  495. value = o2.typeOf(value) === "array" ? value : [value];
  496. var arr = [];
  497. value.each( function( a, i ){
  498. var idx = options.valueList.indexOf( a );
  499. arr.push( idx > -1 ? options.textList[ idx ] : "") ;
  500. });
  501. return arr.join(", ");
  502. });
  503. },
  504. setExcelData: function(d, type){
  505. var arr = this.stringToArray(d);
  506. this.excelData = arr;
  507. if( type === "value" ){
  508. this.setData(arr, true);
  509. }else{
  510. var options = this.getOptionsObj();
  511. this.moduleExcelAG = Promise.resolve(options).then(function (opts) {
  512. arr.each( function( a, i ){
  513. var idx = opts.textList.indexOf( a );
  514. arr[ i ] = idx > -1 ? opts.valueList[ idx ] : null;
  515. });
  516. arr.clean();
  517. var value = arr.length === 1 ? arr[0] : arr;
  518. this.setData(value, true);
  519. this.moduleExcelAG = null;
  520. }.bind(this));
  521. }
  522. },
  523. validationConfigItemExcel: function(data){
  524. if (data.status==="all"){
  525. var n = this.getInputData();
  526. if( typeOf(n)==="array" && n.length === 0 )n = "";
  527. var ed = typeOf( this.excelData ) === "null" ? [] : this.excelData;
  528. if( typeOf(ed)==="array" && ed.length === 0 )ed = "";
  529. var v, ev;
  530. if(data.valueType==="value"){
  531. v = n;
  532. ev = ed;
  533. }else{
  534. v = n.length;
  535. ev = ed.length || 0;
  536. }
  537. switch (data.operateor){
  538. case "isnull":
  539. if (!v)return !ev ? data.prompt : "不在选项中";
  540. break;
  541. case "notnull":
  542. if (v)return data.prompt;
  543. break;
  544. case "gt":
  545. if (v>data.value)return data.prompt;
  546. break;
  547. case "lt":
  548. if (v<data.value)return data.prompt;
  549. break;
  550. case "equal":
  551. if (v==data.value)return data.prompt;
  552. break;
  553. case "neq":
  554. if (v!=data.value)return data.prompt;
  555. break;
  556. case "contain":
  557. if (v.indexOf(data.value)!=-1)return data.prompt;
  558. break;
  559. case "notcontain":
  560. if (v.indexOf(data.value)==-1)return data.prompt;
  561. break;
  562. }
  563. }
  564. return true;
  565. }
  566. });