MUI中小数点的数字输入框,步进step为小数时的需求和浮点数的精确问题
项目需要能步进小数点的数字输入框,但是mui 的数字输入框只能步进整数,发现只要把 源码中的parseInt 改成 parseFloat 就行了,可是后来新的问题又出现了,
浮点数进行加减的精确问题,这是所有编程语言都有的.
下面是完美解决方案,只需将mui.js中关于数字输入框的源代码改成如下即可,mui.js中的位置大概在8158行左右
1 /** 2 * 数字输入框 3 * varstion 1.0.1 4 * by Houfeng 5 * Houfeng@DCloud.io 6 */ 7 8 (function($) { 9 10 var touchSupport = ('ontouchstart' in document); 11 var tapEventName = touchSupport ? 'tap' : 'click'; 12 var changeEventName = 'change'; 13 var holderClassName = 'mui-numbox'; 14 var plusClassSelector = '.mui-btn-numbox-plus,.mui-numbox-btn-plus'; 15 var minusClassSelector = '.mui-btn-numbox-minus,.mui-numbox-btn-minus'; 16 var inputClassSelector = '.mui-input-numbox,.mui-numbox-input'; 17 18 19 this.floatAdd=function(arg1, arg2){ 20 var r1, r2, m, c; 21 try { 22 r1 = arg1.toString().split(".")[1].length; 23 } 24 catch (e) { 25 r1 = 0; 26 } 27 try { 28 r2 = arg2.toString().split(".")[1].length; 29 } 30 catch (e) { 31 r2 = 0; 32 } 33 c = Math.abs(r1 - r2); 34 m = Math.pow(10, Math.max(r1, r2)); 35 if (c > 0) { 36 var cm = Math.pow(10, c); 37 if (r1 > r2) { 38 arg1 = Number(arg1.toString().replace(".", "")); 39 arg2 = Number(arg2.toString().replace(".", "")) * cm; 40 } else { 41 arg1 = Number(arg1.toString().replace(".", "")) * cm; 42 arg2 = Number(arg2.toString().replace(".", "")); 43 } 44 } else { 45 arg1 = Number(arg1.toString().replace(".", "")); 46 arg2 = Number(arg2.toString().replace(".", "")); 47 } 48 return (arg1 + arg2) / m; 49 }, 50 this.floatSub=function(arg1,arg2){ 51 var r1, r2, m, n; 52 try { 53 r1 = arg1.toString().split(".")[1].length; 54 } 55 catch (e) { 56 r1 = 0; 57 } 58 try { 59 r2 = arg2.toString().split(".")[1].length; 60 } 61 catch (e) { 62 r2 = 0; 63 } 64 m = Math.pow(10, Math.max(r1, r2)); //last modify by deeka //动态控制精度长度 65 n = (r1 >= r2) ? r1 : r2; 66 return ((arg1 * m - arg2 * m) / m).toFixed(n); 67 } 68 69 var _this=this; 70 var Numbox = $.Numbox = $.Class.extend({ 71 /** 72 * 构造函数 73 **/ 74 init: function(holder, options) { 75 var self = this; 76 if (!holder) { 77 throw "构造 numbox 时缺少容器元素"; 78 } 79 self.holder = holder; 80 options = options || {}; 81 options.step = parseFloat(options.step || 1); 82 self.options = options; 83 self.input = $.qsa(inputClassSelector, self.holder)[0]; 84 self.plus = $.qsa(plusClassSelector, self.holder)[0]; 85 self.minus = $.qsa(minusClassSelector, self.holder)[0]; 86 self.checkValue(); 87 self.initEvent(); 88 }, 89 /** 90 * 初始化事件绑定 91 **/ 92 initEvent: function() { 93 var self = this; 94 self.plus.addEventListener(tapEventName, function(event) { 95 // var val = parseFloat(self.input.value) + self.options.step; 96 var val=_this.floatAdd(parseFloat(self.input.value),self.options.step); 97 self.input.value = val.toString(); 98 $.trigger(self.input, changeEventName, null); 99 }); 100 self.minus.addEventListener(tapEventName, function(event) { 101 // var val = parseFloat(self.input.value) - self.options.step; 102 var val=_this.floatSub(parseFloat(self.input.value),self.options.step); 103 self.input.value = val.toString(); 104 $.trigger(self.input, changeEventName, null); 105 }); 106 self.input.addEventListener(changeEventName, function(event) { 107 self.checkValue(); 108 var val = parseFloat(self.input.value); 109 //触发顶层容器 110 $.trigger(self.holder, changeEventName, { 111 value: val 112 }); 113 }); 114 }, 115 /** 116 * 获取当前值 117 **/ 118 getValue: function() { 119 var self = this; 120 return parseFloat(self.input.value); 121 }, 122 /** 123 * 验证当前值是法合法 124 **/ 125 checkValue: function() { 126 var self = this; 127 var val = self.input.value; 128 if (val == null || val == '' || isNaN(val)) { 129 self.input.value = self.options.min || 0; 130 self.minus.disabled = self.options.min != null; 131 } else { 132 var val = parseFloat(val); 133 if (self.options.max != null && !isNaN(self.options.max) && val >= parseFloat(self.options.max)) { 134 val = self.options.max; 135 self.plus.disabled = true; 136 } else { 137 self.plus.disabled = false; 138 } 139 if (self.options.min != null && !isNaN(self.options.min) && val <= parseFloat(self.options.min)) { 140 val = self.options.min; 141 self.minus.disabled = true; 142 } else { 143 self.minus.disabled = false; 144 } 145 self.input.value = val; 146 } 147 }, 148 /** 149 * 更新选项 150 **/ 151 setOption: function(name, value) { 152 var self = this; 153 self.options[name] = value; 154 }, 155 /** 156 * 动态设置新值 157 **/ 158 setValue: function(value) { 159 this.input.value = value; 160 this.checkValue(); 161 } 162 163 }); 164 165 $.fn.numbox = function(options) { 166 var instanceArray = []; 167 //遍历选择的元素 168 this.each(function(i, element) { 169 if (element.numbox) { 170 return; 171 } 172 if (options) { 173 element.numbox = new Numbox(element, options); 174 } else { 175 var optionsText = element.getAttribute('data-numbox-options'); 176 var options = optionsText ? JSON.parse(optionsText) : {}; 177 options.step = element.getAttribute('data-numbox-step') || options.step; 178 options.min = element.getAttribute('data-numbox-min') || options.min; 179 options.max = element.getAttribute('data-numbox-max') || options.max; 180 element.numbox = new Numbox(element, options); 181 } 182 }); 183 return this[0] ? this[0].numbox : null; 184 } 185 186 //自动处理 class='mui-locker' 的 dom 187 $.ready(function() { 188 $('.' + holderClassName).numbox(); 189 }); 190 191 }(mui));