用JavaScript替换一个点,结果却把所有内容都删除了。

16

我遇到了一个奇怪的问题。当尝试替换数字输入框中的点时,它会清空整个输入框,而不仅仅是替换那个点。

$("[data-input-payment-id]").on("keyup", function(e) {
  var test_value = $(this).val().replace(/\./g, "");
  $(this).val(test_value);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" data-input-payment-id="12">

JSFIDDLE

如何修改它只删除点?


6
在Firefox、Chrome和Edge上运行良好,但不能使用Internet Explorer,因为那样你将无法使用JSFiddle。 - Jaromanda X
2
@JaromandaX似乎会崩溃,如果您连续输入2个点。 - Pete
6
我在Chrome中测试此内容,但它对我无效。 - Ellisan
2
看起来如果在type = number中使用无效数字,this.value将返回一个空字符串 - 可能相关:https://dev59.com/ImMl5IYBdhLWcg3wHj1O - 而不是删除点,为什么不阻止他们输入点呢? - Pete
@Ellisan - 你在问题中没有提到这是在Chrome中连续输入两个“.”时发生的。 - Jaromanda X
显示剩余8条评论
6个回答

11

我认为(猜测)这是因为您使用了type="number"。然后,跟随小数点的数字,例如123.不是有效的数字,所以val返回空白。

您可以尝试使用以下方法代替:

$("[data-input-payment-id]").on("keyup", function(e) {
  var test_value = this.value.replace(/[^\d,]/g, "");
  $(this).val(test_value);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input data-input-payment-id="12">

此处使用普通文本类型并过滤除数字以外的任何内容进行替换。

编辑:
将正则表达式更改为匹配除数字和逗号以外的任何内容。


问题在于它没有考虑逗号的影响。 - Ellisan
你的意思是什么?任何逗号都被删除了。这不就是你想做的吗? - SamWhan
1
不,我想要删除句点,不是逗号。 - Ellisan

2

这并不是我个人想要的解决方案,但以下是我用来解决问题的方法。我更改了JavaScript代码,使其监听按键码46(即.),并在粘贴事件监听器上返回false以禁止将值粘贴到输入框中。

$("[data-input-payment-id]").on("keypress", function(e) {
  var key = e.charCode ? e.charCode : e.keyCode;
  if (key == 46) {
    return false;
  }
});
$("[data-input-payment-id]").on("paste", function(e) {
  return false;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" data-input-payment-id="12">

它至少在Chrome和Edge浏览器中可用。


@Alnitak 这不是一个好的解决方案,但并非所有的解决方案都是好的解决方案。 - Ellisan
6
尽管可以删除黏贴数据中的“.”,但禁用标准操作是不好的,尤其是对于辅助功能用户来说。 - Alnitak
1
您可能还想监听减号和加号键,因为它们在数字字段中也是允许的,并且可能导致相同的问题。此外,请注意这些键的小键盘版本的键码是不同的。 - cnvzmxcvmcx
此外,当输入为“number”类型时,也可以键入“e”。 - Wiktor Stribiżew
我已经修改了你的解决方案,使其适用于粘贴并且没有条件,并且还可以防止任何额外的字符,例如 e+- - cnvzmxcvmcx

2
我会:
  • 监听事件而非keyup事件,这样可以允许粘贴。
  • 记录先前的正确值,以便可以回滚到它。这是必要的,因为type=number类型的输入在输入变成无效数字时(例如,输入一个小数),其值将立即变为空字符串。我会把先前的正确值存储在input元素的数据属性中。
  • 借助validity.stepMismatch属性,您可以知道当前的值是否违反了input元素的step属性,默认情况下为1。当step为1时,这意味着输入带有小数分隔符的数将被视为不匹配。
  • 由于尾随的小数点分隔符不会产生分数,因此它将通过上述验证。所以当一切正常时,将值发送回输入框:这将消除可能已输入的任何尾随小数点分隔符。

$("[data-input-payment-id]").on("input", function (e) {
    if (!this.validity.stepMismatch) {
        $(this).data("lastValid", $(this).val());
    };
    $(this).val($(this).data("lastValid") || "");  
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number"data-input-payment-id="12">

话虽如此,我个人不赞成以这种方式阻止用户输入:他们可能会认为键盘坏了。在我看来,更好的做法是允许用户随意输入,并在输入框旁边显示一条消息,指示输入无效(直到有效为止)。


吹毛求疵:此解决方案不允许用户清除输入,因为空字符串不是有效的数字。您可能希望明确允许这样做,或在答案中提到它。 - Just a student
1
在我意识到不应该接受分数时,我进一步更新了这个答案。 - trincot
我能理解你这么做的原因,但我想指出(就像你在回答中已经提到的那样),当“步长”不为1时,这根本行不通。例如,使用步长为10时,用户将永远无法通过单个按键输入10的倍数。步长为0.1时也会出现类似的问题。由于问题集中在整数上,所以这应该完全没问题。 - Just a student
@Justastudent,确实step必须是1,这是默认值,也是OP所拥有的。 - trincot

2

您的 Keypress 示例启发了我。如果可以拦截按键事件,就可以在添加实际值之前检查任何验证。此示例还不需要任何条件,并且能够过滤任何非数字值。

$("[data-input-payment-id]").on("keypress", function(e) {
  if ((this.value + e.key).match(/\D/)) {
    return false;
  }
});
$("[data-input-payment-id]").on("paste", function(e) {
  var pasteData = (e.originalEvent.clipboardData || window.clipboardData).getData('text');
  pasteData = pasteData.replace(/\D/g, '');
  this.value = this.value + pasteData;
  return false;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" data-input-payment-id="12">

  • 允许带有过滤的数据粘贴
  • 没有特定的条件限制
  • 可以根据需要进行自定义验证

http://jsfiddle.net/xpvt214o/511118/


1

请查看 MDN文档关于类型为number标签:

表示数字或为空的数字。

如果输入字符串无法转换为正确的数字(例如,如果字符串包含两个点),则访问.value属性将返回空字符串。

.value(和val()函数)仍将返回字符串,但这些字符串必须表示有效的数字(或为空字符串)。而不是无条件地设置元素的值,请先检查该值是否不为空字符串:

$("[data-input-payment-id]").on("keyup", function(e) {
  const val = $(this).val();
  if (val === '') return;
  var test_value = $(this).val().replace(/\./g, "");
  $(this).val(test_value);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" data-input-payment-id="12">

或者您可以使用文本输入框,可能还需要一个pattern属性:

$("[data-input-payment-id]").on("keyup", function(e) {
  const val = $(this).val();
  var test_value = $(this).val().replace(/\./g, "");
  $(this).val(test_value);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
  <input data-input-payment-id="12">
  <input type="submit">
</form>

<form>
<input pattern="^\d+$" data-input-payment-id="12">
<input type="submit">
</form>


1
如果您在代码中键入 123..,则会出现原始问题 - 因此,请尝试在您的代码中键入该内容......一旦您输入了 ..,您就可以键入 123..1.2.3.4.5.6(如果您愿意):p - Jaromanda X

0

$(this).val()如果一个带有type="number"的输入框中有多个.,将返回一个空字符串。

您可以通过仅在$(this).val()不返回空字符串时替换值来解决此问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接