Number.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. MWF.xDesktop.requireApp("process.Xform", "Textfield", null, false);
  2. /** @class Number 数字输入组件。
  3. * @o2cn 数字输入组件
  4. * @example
  5. * //可以在脚本中获取该组件
  6. * //方法1:
  7. * var field = this.form.get("name"); //获取组件
  8. * //方法2
  9. * var field = this.target; //在组件事件脚本中获取
  10. * @extends MWF.xApplication.process.Xform.Textfield
  11. * @o2category FormComponents
  12. * @o2range {Process|CMS}
  13. * @hideconstructor
  14. */
  15. MWF.xApplication.process.Xform.Number = MWF.APPNumber = new Class(
  16. /** @lends MWF.xApplication.process.Xform.Number# */
  17. {
  18. Implements: [Events],
  19. Extends: MWF.APPTextfield,
  20. iconStyle: "numberIcon",
  21. _loadUserInterface: function(){
  22. if ( this.isSectionMergeRead() ) { //区段合并显示
  23. this.node.empty();
  24. this.node.set({
  25. "nodeId": this.json.id,
  26. "MWFType": this.json.type
  27. });
  28. switch (this.json.mergeTypeRead) {
  29. case "amount":
  30. this._loadMergeAmountReadNode();
  31. break;
  32. case "average":
  33. this._loadMergeAverageReadNode();
  34. break;
  35. default:
  36. this._loadMergeReadNode();
  37. break;
  38. }
  39. }else{
  40. if( this.isSectionMergeEdit() ){
  41. switch (this.json.mergeTypeEdit) {
  42. case "amount":
  43. this._loadMergeAmountEidtNode();
  44. break;
  45. case "average":
  46. this._loadMergeAverageEditNode();
  47. }
  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. _loadMergeAmountReadNode: function(){
  59. var data = this.getBusinessDataById();
  60. var total = new Decimal(0);
  61. for( var key in data ){
  62. total = total.plus(new Decimal(data[key] || 0));
  63. }
  64. this.node.set("text", this.formatNumber(total.toString()));
  65. },
  66. _loadMergeAverageReadNode: function(){
  67. var data = this.getBusinessDataById();
  68. var total = new Decimal(0);
  69. for( var key in data ){
  70. total = total.plus(new Decimal(data[key] || 0));
  71. }
  72. var average = total.div( new Decimal(Object.keys(data).length) );
  73. this.node.set("text", this.formatNumber(average.toString()));
  74. },
  75. _loadMergeAmountEidtNode: function(){
  76. var data = this.getBusinessDataById();
  77. var total = new Decimal(0);
  78. for( var key in data ){
  79. total = total.plus(new Decimal(data[key] || 0));
  80. }
  81. this._setBusinessData( total.toNumber() );
  82. this._loadNode();
  83. },
  84. _loadMergeAverageEditNode: function(){
  85. var data = this.getBusinessDataById();
  86. var total = new Decimal(0);
  87. for( var key in data ){
  88. total = total.plus(new Decimal(data[key] || 0));
  89. }
  90. var average = total.div( new Decimal(Object.keys(data).length) );
  91. this._setBusinessData( average.toNumber() );
  92. this._loadNode();
  93. },
  94. isEmpty : function(){
  95. return !this.getData();
  96. },
  97. /**
  98. * @summary 传入值获取适配最大值和最小值的数值.
  99. * @example
  100. * //如果最大值设置为500,最小值为100
  101. *
  102. * var value = this.form.get('field').getRangeValue( 300 );
  103. * //value为300
  104. *
  105. * var value = this.form.get('field').getRangeValue( 10000 );
  106. * //value为500
  107. *
  108. * var value = this.form.get('field').getRangeValue( 1 );
  109. * //value为100
  110. * @param value {String|Nummber}
  111. * @return {Number} 获取适配最大值和最小值的数值.
  112. */
  113. getRangeValue: function( value ){
  114. var v = this.getMax( value );
  115. return this.getMin( v );
  116. },
  117. getMax: function( value ){
  118. if( isNaN(value) )return value;
  119. if( typeOf( value ) === "string" )value = parseFloat(value);
  120. if( !isNaN( this.json.max )){
  121. var max = this.json.max;
  122. if( typeOf( max ) === "string" )max = parseFloat(max);
  123. return Math.min( max, value );
  124. }else{
  125. return value;
  126. }
  127. },
  128. getMin: function( value ){
  129. if( isNaN(value) )return value;
  130. if( typeOf( value ) === "string" )value = parseFloat(value);
  131. if( !isNaN( this.json.min )){
  132. var min = this.json.min;
  133. if( typeOf( min ) === "string" )min = parseFloat(min);
  134. return Math.max( min, value );
  135. }else{
  136. return value;
  137. }
  138. },
  139. getInputData: function( flag ){
  140. var input = this.node.getElement("input");
  141. if (input){
  142. var v = input.get("value");
  143. v = this.unformatNumber( v );
  144. var n = v.toFloat();
  145. n = this.getMax( n );
  146. n = this.getMin( n );
  147. return (isNaN(n)) ? (this.json.emptyValue === "string" ? "" : 0) : n;
  148. }else{
  149. return this._getBusinessData();
  150. }
  151. },
  152. /**
  153. * @summary 传入文本获取清除逗号的数值
  154. * @example
  155. * var value = this.form.get('field').unformatNumber( "30,000" );
  156. * //value为30000
  157. * @param str{String} 文本
  158. * @return {Number} 获取清除逗号的数值.
  159. */
  160. unformatNumber: function(str){
  161. return str.replace(/,/g, "");
  162. },
  163. /**
  164. * @summary 传入文本或数值根据配置的小数位数和分隔符返回字符串
  165. * @example
  166. * //假设组件的设置为千分位分隔,保留小数两位
  167. *
  168. * var value = this.form.get('field').formatNumber( "30000.123" );
  169. * //value为字符串"30,000.12"
  170. *
  171. * var value = this.form.get('field').formatNumber( 30000.123 );
  172. * //value为字符串"30,000.12"
  173. *
  174. * @param str{String|Number}
  175. * @return {Number} 根据配置的小数位数和分隔符返回字符串
  176. */
  177. formatNumber: function(str){
  178. var v = (str || "0").toFloat();
  179. if (v){
  180. if (this.json.decimals && (this.json.decimals!="*")){
  181. var decimals = this.json.decimals.toInt();
  182. var p = Math.pow(10,decimals);
  183. var f_x = Math.round(v*p)/p;
  184. str = f_x.toString();
  185. if (decimals>0){
  186. var pos_decimal = str.indexOf('.');
  187. if (pos_decimal < 0){
  188. pos_decimal = str.length;
  189. str += '.';
  190. }
  191. var decimalStr = (str).substr(pos_decimal+1, (str).length);
  192. while (decimalStr.length < decimals){
  193. str += '0';
  194. decimalStr += 0;
  195. }
  196. }
  197. }
  198. if( this.json.digitsToSeparate && parseInt(this.json.digitsToSeparate) > 1 ){
  199. if( typeOf( str ) === "number" )str = str.toString();
  200. var digits = parseInt(this.json.digitsToSeparate);
  201. var reg = new RegExp( "(\\d{"+digits+"}\\B)" ,"g");
  202. var arr = str.split(".");
  203. var i = arr[0].split("").reverse().join("")
  204. .replace(reg, "$1,")
  205. .split("").reverse().join("");
  206. str = arr.length > 1 ? ( i + "." + arr[1] ) : i ;
  207. }
  208. }
  209. return str;
  210. },
  211. validationFormat: function(){
  212. if( !this.node.getElement("input") )return true;
  213. var n = this.getInputData();
  214. if (isNaN(n)) {
  215. if( n === "" && this.json.emptyValue === "string" ){
  216. return true;
  217. }else{
  218. this.notValidationMode(MWF.xApplication.process.Xform.LP.notValidation_number);
  219. return false;
  220. }
  221. }
  222. return true;
  223. },
  224. // validationFormat: function(){
  225. // if( !this.node.getElement("input") )return true;
  226. // var n = this.node.getElement("input").get("value");
  227. // n = this.unformatNumber(n);
  228. // if (isNaN(n)) {
  229. // if( n === "" && this.json.emptyValue === "string" ){
  230. // return true;
  231. // }else{
  232. // this.notValidationMode(MWF.xApplication.process.Xform.LP.notValidation_number);
  233. // return false;
  234. // }
  235. // }else{
  236. // this.node.getFirst().set("value", this.formatNumber(n));
  237. // }
  238. // return true;
  239. // },
  240. validationConfigItem: function(routeName, data){
  241. var flag = (data.status=="all") ? true: (routeName == data.decision);
  242. if (flag){
  243. var n = this.getInputData();
  244. var strN = n.toString();
  245. if( n === "" && this.json.emptyValue === "string" )n = 0;
  246. var v = (data.valueType=="value") ? n : strN.length;
  247. var strV = (data.valueType=="value") ? strN : strN.length;
  248. switch (data.operateor){
  249. case "isnull":
  250. if (!strV && strV.toString()!=='0'){
  251. this.notValidationMode(data.prompt);
  252. return false;
  253. }
  254. break;
  255. case "notnull":
  256. if (strV){
  257. this.notValidationMode(data.prompt);
  258. return false;
  259. }
  260. break;
  261. case "gt":
  262. if (v>parseFloat(data.value)){
  263. this.notValidationMode(data.prompt);
  264. return false;
  265. }
  266. break;
  267. case "lt":
  268. if (v<parseFloat(data.value)){
  269. this.notValidationMode(data.prompt);
  270. return false;
  271. }
  272. break;
  273. case "equal":
  274. if (v==parseFloat(data.value)){
  275. this.notValidationMode(data.prompt);
  276. return false;
  277. }
  278. break;
  279. case "neq":
  280. if (v!=parseFloat(data.value)){
  281. this.notValidationMode(data.prompt);
  282. return false;
  283. }
  284. break;
  285. case "contain":
  286. if (strV.toString().indexOf(data.value)!=-1){
  287. this.notValidationMode(data.prompt);
  288. return false;
  289. }
  290. break;
  291. case "notcontain":
  292. if (strV.toString().indexOf(data.value)==-1){
  293. this.notValidationMode(data.prompt);
  294. return false;
  295. }
  296. break;
  297. }
  298. }
  299. return true;
  300. },
  301. validationConfig: function(routeName, opinion){
  302. if (this.json.validationConfig){
  303. if (this.json.validationConfig.length){
  304. for (var i=0; i<this.json.validationConfig.length; i++) {
  305. var data = this.json.validationConfig[i];
  306. if (!this.validationConfigItem(routeName, data)) return false;
  307. }
  308. }
  309. return true;
  310. }
  311. return true;
  312. },
  313. _resetNodeEdit: function(){
  314. var input = new Element("input", {
  315. "styles": {
  316. "background": "transparent",
  317. "width": "100%",
  318. "border": "0px"
  319. }
  320. });
  321. var node = new Element("div", {"styles": {
  322. "overflow": "hidden",
  323. "position": "relative",
  324. "margin-right": "20px",
  325. "padding-right": "4px"
  326. }}).inject(this.node, "after");
  327. input.inject(node);
  328. this.node.destroy();
  329. this.node = node;
  330. },
  331. _loadNodeEdit: function(){
  332. debugger;
  333. if (!this.json.preprocessing) this._resetNodeEdit();
  334. var input = this.node.getFirst();
  335. if( !input && this.nodeHtml ){
  336. this.node.set("html", this.nodeHtml);
  337. input = this.node.getFirst();
  338. }
  339. input.set(this.json.properties);
  340. this.node.set({
  341. "id": this.json.id,
  342. "MWFType": this.json.type,
  343. "events": {
  344. "click": this.clickSelect.bind(this)
  345. }
  346. });
  347. if (this.json.showIcon!='no' && !this.form.json.hideModuleIcon) {
  348. this.iconNode = new Element("div", {
  349. "styles": this.form.css[this.iconStyle]
  350. }).inject(this.node, "before");
  351. }else if( this.form.json.nodeStyleWithhideModuleIcon ){
  352. this.node.setStyles(this.form.json.nodeStyleWithhideModuleIcon)
  353. }
  354. this.node.getFirst().addEvent("change", function(){
  355. this.validationMode();
  356. if (this.validation()) {
  357. var value = this.getInputData("change");
  358. this._setBusinessData(value);
  359. this.node.getFirst().set("value", this.formatNumber( value.toString() ));
  360. this.fireEvent("change");
  361. }
  362. }.bind(this));
  363. this.node.getFirst().addEvent("blur", function(){
  364. this.validation();
  365. }.bind(this));
  366. this.node.getFirst().addEvent("keyup", function(){
  367. this.validationMode();
  368. }.bind(this));
  369. },
  370. _computeValue: function(value){
  371. if( this.json.defaultValue && this.json.defaultValue.code){
  372. return this.form.Macro.exec(this.json.defaultValue.code, this)
  373. }else{
  374. if(value){
  375. return value;
  376. }else{
  377. return this.json.emptyValue === "string" ? "" : "0";
  378. }
  379. }
  380. },
  381. __setData: function(data, fireChange){
  382. var old = this.getInputData();
  383. this._setBusinessData(data);
  384. if (this.node.getFirst()){
  385. this.node.getFirst().set("value", this.formatNumber(data));
  386. this.checkDescription();
  387. this.validationMode();
  388. }else{
  389. this.node.set("text", this.formatNumber(data));
  390. }
  391. if (fireChange && old!==data) this.fireEvent("change");
  392. this.moduleValueAG = null;
  393. },
  394. resetData: function(){
  395. var value = this.moduleValueAG || this._getBusinessData();
  396. if (!value) value = this._computeValue();
  397. this.setData(value || "");
  398. },
  399. getValue: function(){
  400. if (this.moduleValueAG) return this.moduleValueAG;
  401. var value = this._getBusinessData();
  402. if( this.json.emptyValue === "string" ){
  403. if( value === "" || typeOf(value)==="null" )value = this._computeValue();
  404. }else{
  405. if( value === "" || value === 0 || typeOf(value)==="null" )value = this._computeValue();
  406. }
  407. if( ( value === "" || typeOf(value)==="null" ) && this.json.emptyValue === "string"){
  408. return "";
  409. }else{
  410. value = this.formatNumber(value);
  411. return value || "0";
  412. }
  413. },
  414. __setValue: function(value){
  415. var v = typeOf( value ) === "string" ? this.unformatNumber( value ) : value;
  416. v = this.isNumber( v ) ? parseFloat( v ) : v;
  417. this._setBusinessData(v);
  418. var val = value;
  419. if( this.json.emptyValue === "string" ){
  420. if( typeOf(v)==="null" )val = "";
  421. if( v === 0 )val = "0";
  422. }else{
  423. if( v === 0 || v === "" || typeOf(v)==="null" )val = "0";
  424. }
  425. if (this.node.getFirst()) this.node.getFirst().set("value", value || val);
  426. if (this.isReadonly()) this.node.set("text", value || val);
  427. this.moduleValueAG = null;
  428. this.fieldModuleLoaded = true;
  429. return value;
  430. },
  431. isNumber : function( d ){
  432. return parseFloat(d).toString() !== "NaN";
  433. },
  434. validationConfigItemExcel: function(data){
  435. if (data.status=="all"){
  436. var n = this.getInputData();
  437. var strN = n.toString();
  438. if( n === "" && this.json.emptyValue === "string" )n = 0;
  439. var v = (data.valueType=="value") ? n : strN.length;
  440. var strV = (data.valueType=="value") ? strN : strN.length;
  441. switch (data.operateor){
  442. case "isnull":
  443. if (!strV && strV.toString()!=='0')return data.prompt;
  444. break;
  445. case "notnull":
  446. if (strV)return data.prompt;
  447. break;
  448. case "gt":
  449. if (v>data.value)return data.prompt;
  450. break;
  451. case "lt":
  452. if (v<data.value)return data.prompt;
  453. break;
  454. case "equal":
  455. if (v==data.value)return data.prompt;
  456. break;
  457. case "neq":
  458. if (v!=data.value)return data.prompt;
  459. break;
  460. case "contain":
  461. if (strV.toString().indexOf(data.value)!=-1)return data.prompt;
  462. break;
  463. case "notcontain":
  464. if (strV.toString().indexOf(data.value)==-1)return data.prompt;
  465. break;
  466. }
  467. }
  468. return true;
  469. }
  470. });