Combox.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  1. MWF.xDesktop.requireApp("process.Xform", "$Selector", null, false);
  2. /** @class Combox 组合框组件。
  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.$Selector
  11. * @o2category FormComponents
  12. * @o2range {Process|CMS}
  13. * @hideconstructor
  14. */
  15. MWF.xApplication.process.Xform.Combox = MWF.APPCombox = new Class(
  16. /** @lends MWF.xApplication.process.Xform.Combox# */
  17. {
  18. Implements: [Events],
  19. Extends: MWF.APP$Selector,
  20. iconStyle: "selectIcon",
  21. options: {
  22. /**
  23. * 手工输入完成后触发。
  24. * @event MWF.xApplication.process.Xform.Combox#commitInput
  25. * @see {@link https://www.yuque.com/o2oa/ixsnyt/hm5uft#i0zTS|组件事件说明}
  26. */
  27. /**
  28. * 值改变时触发。
  29. * @event MWF.xApplication.process.Xform.Combox#change
  30. * @see {@link https://www.yuque.com/o2oa/ixsnyt/hm5uft#i0zTS|组件事件说明}
  31. */
  32. "moduleEvents": ["load", "queryLoad", "postLoad", "commitInput", "change"]
  33. },
  34. initialize: function(node, json, form, options){
  35. this.node = $(node);
  36. this.node.store("module", this);
  37. this.json = json;
  38. this.form = form;
  39. this.field = true;
  40. this.fieldModuleLoaded = false;
  41. },
  42. _loadUserInterface: function(){
  43. if ( this.isSectionMergeRead() ) { //区段合并显示
  44. this._loadMergeReadNode();
  45. }else{
  46. if( this.isSectionMergeEdit() ){
  47. this._loadMergeEditNode();
  48. }else{
  49. this._loadNode();
  50. }
  51. // if (this.json.compute === "show"){
  52. // this._setValue(this._computeValue());
  53. // }else{
  54. // this._loadValue();
  55. // }
  56. }
  57. },
  58. loadVal: function(){
  59. if (this.json.compute === "show"){
  60. this._setValue(this._computeValue());
  61. }else{
  62. this._loadValue();
  63. }
  64. },
  65. /**
  66. * @summary 重新加载组件。会执行postLoad事件。
  67. * @example
  68. * this.form.get("fieldId").reload(); //重新加载事件
  69. */
  70. reload: function(){
  71. if (this.areaNode){
  72. this.node = this.areaNode;
  73. this.areaNode.empty();
  74. this.areaNode = null;
  75. }
  76. this._beforeReloaded();
  77. this._loadUserInterface();
  78. this._loadStyles();
  79. this._afterLoaded();
  80. this._afterReloaded();
  81. this.fireEvent("postLoad");
  82. },
  83. _loadNode: function(){
  84. if (this.isReadonly()){
  85. this._loadNodeRead();
  86. }else{
  87. this._loadNodeEdit();
  88. }
  89. },
  90. _loadNodeRead: function(){
  91. this.node.empty();
  92. this.node.set({
  93. "nodeId": this.json.id,
  94. "MWFType": this.json.type
  95. });
  96. this.loadVal();
  97. //new Element("select").inject(this.node);
  98. },
  99. _loadMergeReadContentNode: function( contentNode, data ){
  100. this.mergeRead = true;
  101. contentNode.setStyles({ "overflow": "hidden"});
  102. var textList = this.getTextListByValue( data.data );
  103. if( typeOf(textList.then) === "function" ){
  104. Promise.resolve(textList).then(function (tList) {
  105. this.__setValueRead( data.data, tList, contentNode );
  106. }.bind(this))
  107. }else{
  108. this.__setValueRead( data.data, textList, contentNode );
  109. }
  110. // textList.each(function(text, i){
  111. // if (i<data.data.length-1) text += this.json.splitShow;
  112. // new Element("div", {"styles": {
  113. // "float": "left",
  114. // "margin-right": "5px"
  115. // },"text": text}).inject( contentNode ); //.inject(this.node.getFirst() || this.node);
  116. // }.bind(this));
  117. },
  118. _loadNodeEdit: function(){
  119. var options = this.getOptions();
  120. if( typeOf(options.then) === "function" ){
  121. Promise.resolve(options).then(function (opt) {
  122. this.__loadNodeEdit(opt);
  123. this.loadVal();
  124. this._loadStyles();
  125. }.bind(this))
  126. }else{
  127. this.__loadNodeEdit(options);
  128. this.loadVal();
  129. }
  130. },
  131. __loadNodeEdit: function(opt){
  132. this.node.empty();
  133. var select;
  134. MWF.require("MWF.widget.Combox", function(){
  135. select = this.combox = new MWF.widget.Combox({
  136. "style": this.form.json.comboxStyle ? this.form.json.comboxStyle.style : "default",
  137. "positionX": this.form.json.addressStyle ? this.form.json.addressStyle.positionX : "left",
  138. "onlySelect": this.json.onlySelect==="y",
  139. "count": this.json.count.toInt() || 0,
  140. "splitStr": this.json.splitStr || ",\\s*|;\\s*|,\\s*|;\\s*",
  141. "splitShow": this.json.splitShow || ", ",
  142. "focusList": this.json.showOptions === "focus",
  143. "list": opt,
  144. "onCommitInput": function(item){
  145. this.fireEvent("commitInput");
  146. }.bind(this),
  147. "onChange": function(){
  148. this.fireEvent("change");
  149. }.bind(this),
  150. "optionsMethod": this._searchOptions()
  151. });
  152. }.bind(this), false);
  153. // var select = new Element("select");
  154. // select.set(this.json.properties);
  155. select.inject(this.node);
  156. //this.node.destroy();
  157. // this.areaNode = this.node;
  158. // this.node = select;
  159. this.node.set({
  160. "id": this.json.id,
  161. "MWFType": this.json.type
  162. });
  163. this.combox.addEvent("change", function(){
  164. this.validationMode();
  165. if (this.validation()){
  166. var v = this.getInputData("change");
  167. this._setBusinessData(v);
  168. }
  169. }.bind(this));
  170. },
  171. _loadStyles: function(){
  172. if (this.json.styles) this.node.setStyles(this.json.styles);
  173. if (this.json.inputStyles && !this.mergeRead) if (this.node.getFirst()) this.node.getFirst().setStyles(this.json.inputStyles);
  174. if (this.iconNode && this.iconNode.offsetParent !== null){
  175. var size = this.node.getSize();
  176. //if (!size.y){
  177. // var y1 = this.node.getStyle("height");
  178. // var y2 = this.node.getFirst().getStyle("height");
  179. // alert(y1+"," +y2);
  180. // var y = ((y1!="auto" && y1>y2) || y2=="auto") ? y1 : y2;
  181. // size.y = (y=="auto") ? "auto" : y.toInt();
  182. // //alert(size.y)
  183. //}
  184. this.iconNode.setStyle("height", ""+size.y+"px");
  185. //alert(this.iconNode.getStyle("height"))
  186. }
  187. },
  188. _searchOptions: function(){
  189. if (this.json.itemType === "dynamic"){
  190. return function(value, callback){
  191. var event = {
  192. "value": value,
  193. "callback": callback
  194. };
  195. this.form.Macro.fire(((this.json.itemDynamic) ? this.json.itemDynamic.code : ""), this, event);
  196. }.bind(this);
  197. }else{
  198. return null;
  199. }
  200. },
  201. /**
  202. * @summary 获取选择项。
  203. * @return {Array | Promise} 返回选择项数组或Promise,如:<pre><code class='language-js'>[
  204. * "女|female",
  205. * "男|male"
  206. * ]</code></pre>
  207. * @example
  208. * this.form.get('fieldId').getOptions();
  209. * @example
  210. * //异步
  211. * var opt = this.form.get('fieldId').getOptions();
  212. * Promise.resolve(opt).then(function(options){
  213. * //options为选择项数组
  214. * })
  215. */
  216. getOptions: function(async, refresh){
  217. if( this.optionsCache && !refresh )return this.optionsCache;
  218. this.optionsCache = null;
  219. var opt = this._getOptions(async, refresh);
  220. if( (opt && typeOf(opt.then) === "function") ){
  221. var p = Promise.resolve( opt ).then(function(option){
  222. this.moduleSelectAG = null;
  223. this.optionsCache = this.parseOptions(option || []);
  224. return this.optionsCache;
  225. }.bind(this));
  226. this.moduleSelectAG = p;
  227. return p;
  228. }else{
  229. this.optionsCache = this.parseOptions(opt || []);
  230. return this.optionsCache;
  231. }
  232. },
  233. parseOptions: function(list){
  234. // var list = [];
  235. // if (this.json.itemType === "values"){
  236. // list = this.json.itemValues;
  237. // }else if (this.json.itemType === "script"){
  238. // list = this.form.Macro.exec(((this.json.itemScript) ? this.json.itemScript.code : ""), this);
  239. // }
  240. if (list.length){
  241. var options = [];
  242. list.each(function(v){
  243. if (typeOf(v)==="object"){
  244. options.push(v);
  245. }else{
  246. v = v.toString();
  247. var arr = v.split("|");
  248. var o = { "text": "", "keyword": "", "value": "" };
  249. switch (arr.length){
  250. case 0: break;
  251. case 1:
  252. o.text = arr[0];
  253. o.keyword = arr[0];
  254. o.value = arr[0];
  255. break;
  256. case 2:
  257. o.text = arr[0];
  258. o.keyword = arr[0];
  259. o.value = arr[1];
  260. break;
  261. case 3:
  262. o.text = arr[0];
  263. o.keyword = arr[1];
  264. o.value = arr[2];
  265. break;
  266. default:
  267. o.text = arr[0];
  268. o.keyword = arr[1];
  269. o.value = arr[2];
  270. }
  271. options.push(o);
  272. }
  273. }.bind(this));
  274. return options;
  275. }
  276. return [];
  277. },
  278. /**
  279. * 当表单上没有对应组件的时候,可以使用this.data[fieldId] = data赋值。
  280. * @summary 为组件赋值。
  281. * @param value{String} .
  282. * @example
  283. * this.form.get("fieldId").setData("test"); //赋文本值
  284. * @example
  285. * //如果无法确定表单上是否有组件,需要判断
  286. * if( this.form.get('fieldId') ){ //判断表单是否有无对应组件
  287. * this.form.get('fieldId').setData( data );
  288. * }else{
  289. * this.data['fieldId'] = data;
  290. * }
  291. */
  292. setData: function(value){
  293. this._setBusinessData(value);
  294. this._setValue(value);
  295. },
  296. _setValue: function(value){
  297. if (!value) value = [];
  298. if (value.length==1 && (!value[0])) value = [];
  299. if (typeOf(value) !=="array") value = [value];
  300. if (this.combox){
  301. var textData = this.getTextData( value );
  302. if( typeOf(textData.then) === "function" ){
  303. Promise.resolve(textData).then(function (tData) {
  304. this.combox.clear();
  305. this.__setValueEdit( tData );
  306. }.bind(this))
  307. }else{
  308. this.combox.clear();
  309. this.__setValueEdit( textData )
  310. }
  311. }else{
  312. var textList = this.getTextListByValue( value );
  313. if( typeOf(textList.then) === "function" ){
  314. Promise.resolve(textList).then(function (tList) {
  315. this.__setValueRead( value, tList );
  316. }.bind(this))
  317. }else{
  318. this.__setValueRead( value, textList );
  319. }
  320. }
  321. },
  322. __setValueEdit: function(textData){
  323. var comboxValues = [];
  324. textData.value.each(function(v, i){
  325. comboxValues.push({
  326. "text": textData.text[i] || v,
  327. "value": v
  328. });
  329. }.bind(this));
  330. this.combox.addNewValues(comboxValues);
  331. this.fieldModuleLoaded = true;
  332. },
  333. __setValueRead: function(value, textList, contentNode){
  334. if(!contentNode)contentNode = new Element("div", {
  335. "styles": { "overflow": "hidden"}
  336. }).inject(this.node);
  337. textList.each(function(text, i){
  338. if (i<value.length-1) text += this.json.splitShow;
  339. new Element("div", {"styles": {
  340. "float": "left",
  341. "margin-right": "5px"
  342. },"text": text}).inject( contentNode ); //.inject(this.node.getFirst() || this.node);
  343. }.bind(this));
  344. this.fieldModuleLoaded = true;
  345. },
  346. /**
  347. * @summary 重新计算下拉选项.
  348. * @param {Function} callback 回调方法
  349. * @example
  350. * this.form.get('fieldId').resetOption();
  351. * @example
  352. * this.form.get('fieldId').resetOption(function(){
  353. * //设置完成后的回调
  354. * });
  355. */
  356. resetOption: function( callback ){
  357. if (this.combox){
  358. var list = this.getOptions(true, true);
  359. if( typeOf(list.then) === "function" ){
  360. Promise.resolve(list).then(function (array) {
  361. this.combox.setOptions({"list": array});
  362. if(callback)callback();
  363. })
  364. }else{
  365. this.combox.setOptions({"list": list});
  366. if(callback)callback();
  367. }
  368. }
  369. },
  370. /**
  371. * @summary 添加下拉选项.
  372. * @param text {String} 下拉选项文本
  373. * @param value {String} 下拉选项值
  374. * @example
  375. * this.form.get('fieldId').addOption("秘密","level1");
  376. */
  377. addOption: function(text, value){
  378. if (this.combox){
  379. var list = this.combox.options.list || [];
  380. list.push({
  381. "text": text,
  382. "value": value
  383. });
  384. this.combox.setOptions({"list": list});
  385. }
  386. },
  387. isEmpty : function(){
  388. var data = this.getData();
  389. if( typeOf(data) === "array" ){
  390. return data.length === 0;
  391. }else{
  392. return !data;
  393. }
  394. },
  395. getInputData: function(){
  396. if (this.combox) return this.combox.getData();
  397. return this._getBusinessData();
  398. },
  399. _beforeReloaded: function(){
  400. if( this.combox )this.combox.clear();
  401. this.combox = null;
  402. },
  403. /**
  404. * @summary 获取选中项的text。
  405. * @return {Array|Promise} 返回选中项的text
  406. * @example
  407. * var text = this.form.get('fieldId').getText(); //获取选中项的文本
  408. * @example
  409. * //如果选项是异步的,比如数据字典、视图、查询视图
  410. * var p = this.form.get('fieldId').getText(); //获取选中项Promise
  411. * Promise.resolve(p).then(function(text){
  412. * //text 为选选中项的文本
  413. * })
  414. */
  415. getText: function(){
  416. var d = this.getTextData();
  417. if( typeOf(d.then) === "function" ){
  418. return d.then(function( d1 ){
  419. return d1.text;
  420. });
  421. }else{
  422. return d.text;
  423. }
  424. },
  425. /**
  426. * @summary 获取选中的值和文本.
  427. * @example
  428. * var array = this.form.get('fieldId').getTextData();
  429. * @example
  430. * //异步
  431. * var array = this.form.get('fieldId').getTextData();
  432. * Promise.resolve(array).then(function(arr){
  433. * //arr为选中项值和文本
  434. * })
  435. * @return {Object|Promise} 返回选中项值和文本,格式为 { 'value' : [value], 'text' : [text] }.
  436. */
  437. getTextData: function( value ){
  438. var v = value || this.getData();
  439. var textList = this.getTextListByValue( v );
  440. if( typeOf(textList.then) === "function" ){
  441. return Promise.resolve(textList).then(function (tList) {
  442. return {"value": v, "text": tList.length ? tList : v};
  443. }.bind(this));
  444. }else{
  445. return {"value": v, "text": textList.length ? textList : v};
  446. }
  447. //return this.node.get("text");
  448. },
  449. getTextListByValue: function( v ){
  450. var options, textList=[];
  451. if( this.json.itemType === "dynamic" ){
  452. var fun = this._searchOptions();
  453. if( fun ){
  454. v.each(function ( i ) {
  455. var text;
  456. if (typeOf(i)==="object"){
  457. text = i.text || i.title || i.subject || i.name;
  458. }else{
  459. i = i.toString();
  460. fun(i, function( options ){
  461. var matchList = options.filter(function (o) {
  462. if( o.value === i )return true;
  463. });
  464. text = (matchList[0] && matchList[0].text) ? matchList[0].text : i;
  465. textList.push( text );
  466. }.bind(this));
  467. }
  468. }.bind(this));
  469. return textList;
  470. }
  471. }else{
  472. options = this.getOptions();
  473. if( typeOf(options.then) === "function" ){
  474. return Promise.resolve(options).then(function (opt) {
  475. return this._getTextListByValue(v, opt);
  476. }.bind(this));
  477. }else{
  478. return this._getTextListByValue(v, options);
  479. }
  480. }
  481. v.each(function ( i ) {
  482. var text;
  483. if (typeOf(i)==="object"){
  484. text = i.text || i.title || i.subject || i.name;
  485. }else{
  486. text = i.toString();
  487. }
  488. textList.push( text );
  489. }.bind(this));
  490. return textList;
  491. },
  492. _getTextListByValue: function(v, options){
  493. var textList = [];
  494. v.each(function ( i ) {
  495. var text;
  496. if (typeOf(i)==="object"){
  497. text = i.text || i.title || i.subject || i.name;
  498. }else{
  499. i = i.toString();
  500. var matchList = options.filter(function (o) {
  501. if( o.value === i )return true;
  502. });
  503. text = (matchList[0] && matchList[0].text) ? matchList[0].text : i;
  504. }
  505. textList.push( text );
  506. }.bind(this));
  507. return textList;
  508. },
  509. getValueListByText: function( text ){
  510. var options, valueList=[];
  511. if( this.json.itemType === "dynamic" ){
  512. }else{
  513. options = this.getOptions();
  514. if( typeOf(options.then) === "function" ){
  515. return Promise.resolve(options).then(function (opt) {
  516. return this._getValueListByText(text, opt);
  517. }.bind(this));
  518. }else{
  519. return this._getValueListByText(text, options);
  520. }
  521. }
  522. text.each(function ( i ) {
  523. var value;
  524. if (typeOf(i)==="object"){
  525. value = i.name || i.text || i.title || i.subject ;
  526. }else{
  527. value = i.toString();
  528. }
  529. valueList.push( value );
  530. }.bind(this));
  531. return valueList;
  532. },
  533. _getValueListByText: function(text, options){
  534. var valueList = [];
  535. text.each(function ( i ) {
  536. var value;
  537. if (typeOf(i)==="object"){
  538. value = i.name || i.text || i.title || i.subject;
  539. }else{
  540. i = i.toString();
  541. var matchList = options.filter(function (o) {
  542. if( o.text === i )return true;
  543. });
  544. value = (matchList[0] && matchList[0].text) ? matchList[0].value : i;
  545. }
  546. valueList.push( value );
  547. }.bind(this));
  548. return valueList;
  549. },
  550. resetData: function(){
  551. //this._setBusinessData(this.getValue());
  552. this.setData(this.getValue());
  553. },
  554. getExcelData: function( type ){
  555. var value = this.getData();
  556. if( type === "value" )return o2.typeOf(value) === "array" ? value.join(", ") : value;
  557. var textList = this.getTextListByValue( value );
  558. return Promise.resolve(textList).then(function (tList) {
  559. return tList.join(", ");
  560. });
  561. },
  562. setExcelData: function(data, type){
  563. var arr = this.stringToArray(data);
  564. this.excelData = arr;
  565. if( type === "value" ){
  566. this.setData(arr, true);
  567. }else{
  568. var values = this.getValueListByText( arr );
  569. this.moduleExcelAG = Promise.resolve(values).then(function (vs) {
  570. this.setData(vs, true);
  571. this.moduleExcelAG = null;
  572. }.bind(this));
  573. }
  574. }
  575. });