;
(function ($) {
/**
* 数字控件
*
* @example
* var editor = new FR.NumberEditor({
* renderEl : 'body',
* allowDecimals : true,
* allowNegative : true,
* decimalPrecision : -1,
* autoVerify : true,
* decimalSeparator : ".",
* value : -233.455
* });
*
* @class FR.NumberEditor
* @extends FR.EditComp
* @cfg {JSON} options 属性配置
* @cfg {Boolean} [options.allowDecimals=true] 是否允许小数
* @cfg {Boolean} [options.allowNegative=true] 是否允许负数
* @cfg {Number} [options.decimalPrecision=-1] 小数精确度
* @cfg {String} [options.decimalSeparator=.] 小数分割符
*/
FR.NumberEditor = FR.extend(FR.EditComp, /**@class FR.NumberEditor*/{
_defaultConfig: function () {
return $.extend(FR.NumberEditor.superclass._defaultConfig.apply(), {
allowDecimals: true,
allowNegative: true,
decimalPrecision: -1,
autoVerify: true,
decimalSeparator: '.'// decimal的分隔符
// alex:不添加value:0作为默认值,这样会导致在BS编辑的时候,如果写的是0,发现isDirty ==
// false,而不赋值
});
},
_init: function () {
FR.NumberEditor.superclass._init.apply(this, arguments);
var o = this.options;
var baseChars = '0123456789';
this.allowed = baseChars + '';
if (o.allowDecimals) {
this.allowed += '.';
}
if (o.allowNegative) {
this.allowed += "-";
}
// b:屏蔽输入法
this.editComp.css("ime-mode", "disabled");
var self = this;
this.editComp.blur(function () {
if ('.' == self.editComp.val().charAt(0)) {
self.editComp.val('0' + self.editComp.val());
}
}).keydown(function (e) {
// wei : 不触发参数界面查询按钮
if (e.keyCode == FR.keyCode.ENTER && !self.options.write) {
e.stopPropagation();
}
}).keypress(function (e) {
// james:下面是抄的Ext的
var k = e.keyCode;
if (!$.browser.msie
&& (FR.isNavKeyPress(e) || FR.isSpecialKey(e) || k == FR.keyCode.BACKSPACE)) {
return;
}
var c = e.charCode || e.keyCode;// james:IE当中要取keyCode
var cc = String.fromCharCode(c);
// if($.browser.msie && (FR.isSpecialKey(e) || !cc)){
// 过滤掉回车(ASCII为13)和ESC(ASCII为27)
if ($.browser.msie && (c === 27 || c === 13)) {
return;
}
if (self.allowed.indexOf(cc) === -1) {
// FR.Msg.toast(errorMsg);
e.preventDefault();
}
if (this.value.indexOf('.') > -1 && cc == '.') {
// FR.Msg.toast(errorMsg);
e.preventDefault();
}
});
},
isValidateInput: function (e) {
var c = e.charCode || e.keyCode;// james:IE当中要取keyCode
// wei:backspace
if (c == FR.keyCode.BACKSPACE || c == FR.keyCode.ENTER) {
return true;
}
// 上面数字键盘是48-57 数字小键盘是96-105 同样小数点也要考虑两个
if (c >= 96 && c <= 105) {
c = c - 48;
}
var cc = String.fromCharCode(c);
if (c === 190 || c === 110) {
cc = ".";
}
return (this.allowed.indexOf(cc) > -1)
&& (cc != '.' || (this.editComp.val().substr(0, this.editComp.val().length - 1)).indexOf('.') === -1);
},
_dealValueWithEvents: function (value) {
var oldValue = this.getValue();
var txt;
if (typeof oldValue == 'string' && oldValue != '') {
txt = oldValue;
} else {
// value = parseFloat(value);
txt = String(value);
}
this.editComp.val( txt.replace(".",
this.options.decimalSeparator));
// alex:把老的值保存在this.options.value中,用来判断isDirty
if (arguments[1] !== false) {
this.fireEvent(FR.Events.CHANGE, value, oldValue); // fire value
// change event,
// newValue &
// oldValue
}
},
_fixPrecision: function (value) {
var nan = isNaN(value);
if (!this.options.allowDecimals || this.options.decimalPrecision == -1
|| nan || !value) {
return nan ? '' : value;
}
return parseFloat(parseFloat(value).toFixed(this.options.decimalPrecision));
},
// float只能支持到17位,而21位才开始转化成科学计数法,
// 17到21位会出错,21位以上位数正常但是会舍掉一部分 todo
_parseValue: function (value) {
value = parseFloat(String(value).replace(this.options.decimalSeparator, "."));
return isNaN(value) ? '' : value;
},
// james:对于数字编辑器的返回值,如果没有值,就返回'',如果输入的是0,就返回0
// 这个地方要看用户的反馈,是否需要提供可配置的地方。
getValue: function () {
var txt = this.editComp.val();
if (txt.length > 17) {
return txt;
}
return this._fixPrecision(this._parseValue(txt));
},
verifyDedimals: function () {
if (typeof this.editComp.reg == "undefined") {
this.editComp.reg = (this.options.allowNegative ? "\-?" : "")
+ "\\d+"
+ (this.options.allowDecimals ? ("(\\.\\d{0,"
+ this.options.maxDecLength + "})?") : "");
}
var pattern = new RegExp(this.editComp.reg);
var result = pattern.exec(this.editComp.val());
if (result != null) {
return result[0];
}
return "";
},
recoveryValue: function () {
this.editComp.val(isNaN(this.options.oldValue)
? ''
: String(this.options.oldValue).replace(".",
this.options.decimalSeparator));
},
isValidate: function (cValue) {
var value = cValue != null && cValue != undefined
? cValue
: this.editComp.val();
if(cValue && this.options.isEditable && (''+ cValue).indexOf(',') != -1){
value = value.replace(/,/g, "");
}
// richer:不允许为空
// b: 不确定这么改有没有问题
// value==""时如果value=0则表达式为ture,放在最后安全
if (value == null || value == undefined || value === "") {
if (this.options.allowBlank !== false) {
return true;
} else {
this.errorMsg = this.options.errorMsg || FR.i18nText("FR-Base_NOT_NULL_Des");
return false;
}
}
value = ('' + value).replace(this.options.decimalSeparator, ".");
if (isNaN(value)) {
this.errorMsg = this.options.errorMsg
|| FR.i18nText("Err-The_value_must_be_number");
return false;
}
// 不允许为小数
// 数字太大parseFloat就变成科学计数法的形式了 而且总位数17以上的小数会被截断
var str = value;
var bd = new FR.BigDecimal({
numStr: str
});
if (str.indexOf(this.options.decimalSeparator) > 0) {
if (!this.options.allowDecimals) {
this.errorMsg = this.options.errorMsg
|| FR.i18nText("Err-The_value_must_be_integer");
return false;
} else {
if (str.length - str.indexOf(this.options.decimalSeparator) > this.options.maxDecLength + 1) {
this.errorMsg = this.options.errorMsg
|| FR.i18nText("FR-Base_DecimalNumber_Out");
return false;
}
}
}
// 不允许为负数
if (!this.options.allowNegative && !bd.isPositive()) {
this.errorMsg = this.options.errorMsg
|| FR.i18nText("FR-Report_Invalid_Cell");
return false;
}
if (this.options.minValue != null &&
bd.lessThan(new FR.BigDecimal({numStr: String(this.options.minValue)}))) {
this.errorMsg = this.options.errorMsg
|| FR.i18nText("Err-The_number_is_less_than_the_minimum_value")
+ this.options.minValue;
return false;
}
if (this.options.maxValue != null &&
bd.greaterThan(new FR.BigDecimal({numStr: String(this.options.maxValue)}))) {
this.errorMsg = this.options.errorMsg
|| FR.i18nText("Err-The_number_is_larger_than_the_maximum_value")
+ this.options.maxValue;
return false;
}
return true;
},
doResize: function (give) {
FR.NumberEditor.superclass.doResize.call(this, give);
}
});
$.shortcut("number", FR.NumberEditor);
/**
* 双精度数处理函数
* @param {JSON} config 配置属性
* @constructor
*/
FR.BigDecimal = function (config) {
this.options = $.extend({
numStr: '',
decimalSeparator: '.'
}, config);
var o = this.options;
var str = o.numStr;
// 正数
this.positive = true;
// 整数部分
this.intArray = [];
// 小数部分
this.decArray = [];
//
if (str.indexOf("e") !== -1 || str.indexOf("E") !== -1) {
}
var i=0;
var dealPos = true;
if (str.charAt(0).match(/[-+]/)) {
this.positive = str.charAt(0) == '+';
i ++;
}
for (; i<str.length; i++) {
var c = str.charAt(i);
if (c == o.decimalSeparator) {
dealPos = false;
continue;
}
if (dealPos) {
this.intArray.push(c);
} else {
this.decArray.push(c);
}
}
};
$.extend(FR.BigDecimal.prototype, {
isPositive: function() {
return this.positive;
},
equalsTo: function(bigDecimal) {
return this.compareTo(bigDecimal) === 0;
},
greaterThan: function(bigDecimal) {
return this.compareTo(bigDecimal) === 1;
},
lessThan: function(bigDecimal) {
return this.compareTo(bigDecimal) === -1;
},
compareTo: function(bigDecimal) {
if (bigDecimal == null) {
return null;
}
if (this.isPositive() && !bigDecimal.isPositive()) {
return 1;
}
if (!this.isPositive() && bigDecimal.isPositive()) {
return -1;
}
var res = 0;
var arr = this.intArray;
if (arr.length > bigDecimal.intArray.length) {
res = 1;
} else if (arr.length < bigDecimal.intArray.length) {
res = -1;
} else {
for (var i=0; i<arr.length; i++) {
if (arr[i] > bigDecimal.intArray[i]) {
res = 1;
break;
} else if (arr[i] < bigDecimal.intArray[i]) {
res = -1;
break;
}
}
if (res === 0) {
var decArr = this.decArray;
var decLen = Math.min(decArr.length, bigDecimal.decArray.length);
for (var j= 0; j<decLen; j++) {
if (decArr[j] > bigDecimal.decArray[j]) {
res = 1;
break;
} else if (decArr[j] < bigDecimal.decArray[j]) {
res = -1;
break;
}
}
if (res === 0) {
if (decArr[decLen] != null) {
res = 1;
} else if (bigDecimal.decArray[decLen] != null) {
res = -1;
}
}
}
}
return this.isPositive() ? res : -res;
}
});
})(jQuery);