簡體   English   中英

如何使用 html5 輸入類型號處理浮點數和小數點分隔符

[英]How to handle floats and decimal separators with html5 input type number

我正在構建主要用於移動瀏覽器的網絡應用程序。 我使用數字類型的輸入字段,因此(大多數)移動瀏覽器僅調用數字鍵盤以獲得更好的用戶體驗。 這個網絡應用程序主要用於小數點分隔符是逗號而不是點的區域,所以我需要處理這兩個小數點分隔符。

如何用點和逗號覆蓋整個混亂?

我的發現:

桌面版 Chrome

  • 輸入類型=數字
  • 用戶輸入“4,55”到輸入字段
  • $("#my_input").val(); 返回“455”
  • 我無法從輸入中獲得正確的值

桌面版火狐

  • 輸入類型=數字
  • 用戶輸入“4,55”到輸入字段
  • $("#my_input").val(); 返回“4,55”
  • 沒關系,我可以用點替換逗號並獲得正確的浮點數

安卓瀏覽器

  • 輸入類型=數字
  • 用戶輸入“4,55”到輸入字段
  • 當輸入失去焦點時,值被截斷為“4”
  • 混淆用戶

視窗電話 8

  • 輸入類型=數字
  • 用戶輸入“4,55”到輸入字段
  • $("#my_input").val(); 返回“4,55”
  • 沒關系,我可以用點替換逗號並獲得正確的浮點數

在這種情況下,當用戶可能使用逗號或點作為小數點分隔符並且我想將 html 輸入類型保留為數字以提供更好的用戶體驗時,“最佳實踐”是什么?

我可以將逗號轉換為“動態”的點,綁定鍵事件,它是否適用於數字輸入?

編輯

Currenlty 我沒有任何解決方案,如何從類型設置為數字的輸入中獲取浮點值(作為字符串或數字)。 如果最終用戶輸入“4,55”,Chrome 總是返回“455”,Firefox 返回“4,55”,這很好。

同樣令人討厭的是,在Android(經過測試的4.2模擬器)中,當我在輸入字段中輸入“4,55”並將焦點更改為其他位置時,輸入的數字會被截斷為“4”。

我認為上面的答案中缺少的是需要為step屬性指定不同的值,其默認值為1 如果您希望輸入的驗證算法允許浮點值,請相應地指定一個步驟。

例如,我想要美元金額,所以我指定了這樣的步驟:

 <input type="number" name="price"
           pattern="[0-9]+([\.,][0-9]+)?" step="0.01"
            title="This should be a number with up to 2 decimal places.">

使用 jQuery 檢索值並沒有錯,但是您會發現直接使用 DOM API 來獲取元素的validity.valid屬性很有用。

我對小數點有類似的問題,但我意識到存在問題的原因是 Twitter Bootstrap 添加到具有無效值的數字輸入的樣式。

這是一個演示添加step屬性使其工作的小提琴,並測試當前值是否有效:

TL;DR:將 a step屬性設置為浮點值,因為它默認為1

注意:逗號對我無效,但我懷疑如果我將操作系統語言/區域設置設置為使用逗號作為小數點分隔符的地方,它會起作用。 *注意事項*:Ubuntu/Gnome 14.04 中的操作系統語言/鍵盤設置 *德語* 並非如此。

根據 w3.org,數字輸入value屬性被定義為浮點數 浮點數的語法似乎只接受點作為小數點分隔符。

我在下面列出了一些可能對您有幫助的選項:

1.使用pattern屬性

使用pattern屬性,您可以以 HTML5 兼容的方式使用正則表達式指定允許的格式。 如果模式失敗,您可以在此處指定允許使用逗號字符和有用的反饋消息。

<input type="number" pattern="[0-9]+([,\.][0-9]+)?" name="my-num"
           title="The number input must start with a number and use either comma or a dot as a decimal character."/>

注意:跨瀏覽器支持差異很大。 它可能是完整的、部分的或不存在的。

2. JavaScript 驗證

您可以嘗試將一個簡單的回調綁定到例如onchange (和/或blur )事件,該事件將替換逗號或一起驗證。

3.禁用瀏覽器驗證##

第三,您可以嘗試在數字輸入上使用formnovalidate屬性,目的是一起禁用該字段的瀏覽器驗證。

<input type="number" formnovalidate />

4. 組合..?

<input type="number" pattern="[0-9]+([,\.][0-9]+)?" 
           name="my-num" formnovalidate
           title="The number input must start with a number and use either comma or a dot as a decimal character."/>

是使用逗號還是句點作為小數點分隔符完全取決於瀏覽器。 瀏覽器根據操作系統或瀏覽器的區域設置做出決定,或者某些瀏覽器從網站獲取提示。 我制作了一個瀏覽器對比圖,展示了不同瀏覽器如何支持處理不同的本地化方法。 Safari 是唯一可以交替處理逗號和句點的瀏覽器。

基本上,您作為網絡​​作者無法真正控制這一點。 一些變通方法涉及使用兩個帶有整數的輸入字段。 這允許每個用戶按預期輸入數據。 它不是特別性感,但它適用於所有用戶的所有情況。

使用valueAsNumber代替.val()

輸入 。 valueAsNumber [ = 值 ]

如果適用,返回表示表單控件值的數字; 否則,返回 null。
可以設置,改變值。
如果控件既不是基於日期或時間也不是數字,則拋出 INVALID_STATE_ERR 異常。

使用文本類型但強制顯示數字鍵盤

<input value="12,4" type="text" inputmode="numeric" pattern="[-+]?[0-9]*[.,]?[0-9]+">

inputmode 標簽是解決方案

我還沒有找到完美的解決方案,但我能做的最好的事情是使用 type="tel" 並禁用 html5 驗證 (formnovalidate):

<input name="txtTest" type="tel" value="1,200.00" formnovalidate="formnovalidate" />

如果用戶輸入逗號,它將在我嘗試過的每個現代瀏覽器(最新的 FF、IE、edge、opera、chrome、safari 桌面、android chrome)中以逗號輸出。

主要問題是:

  • 移動用戶將看到他們的電話鍵盤,這可能與數字鍵盤不同。
  • 更糟糕的是,電話鍵盤甚至可能沒有逗號鍵。

對於我的用例,我只需要:

  • 用逗號顯示初始值(firefox 把它去掉,因為 type=number)
  • 不會失敗 html5 驗證(如果有逗號)
  • 將字段完全按照輸入讀取(可能帶有逗號)

如果您有類似的要求,這應該適合您。

注意:我不喜歡模式屬性的支持。 formnovalidate 似乎工作得更好。

當你調用$("#my_input").val(); 它作為字符串變量返回。 所以使用parseFloatparseInt進行轉換。 當您使用parseFloat您的桌面或手機本身就理解變量的含義。

此外,您可以使用toFixed將浮點數轉換為字符串,該參數具有如下所示的數字計數參數:

var i = 0.011;
var ss = i.toFixed(2); //It returns 0.01

顯然瀏覽器仍然有問題(盡管 Chrome 和 Firefox Nightly 做得很好)。 對於真正必須使用數字字段的人(可能是因為文本字段沒有小箭頭),我有一個很笨的方法。

我的解決方案

我在表單輸入中添加了一個keyup事件處理程序並跟蹤狀態並在它再次有效時設置該值。

純 JS 代碼段JSFIDDLE

 var currentString = ''; var badState = false; var lastCharacter = null; document.getElementById("field").addEventListener("keyup",($event) => { if ($event.target.value && !$event.target.validity.badInput) { currentString = $event.target.value; } else if ($event.target.validity.badInput) { if (badState && lastCharacter && lastCharacter.match(/[\\.,]/) && !isNaN(+$event.key)) { $event.target.value = ((+currentString) + (+$event.key / 10)); badState = false; } else { badState = true; } } document.getElementById("number").textContent = $event.target.value; lastCharacter = $event.key; }); document.getElementById("field").addEventListener("blur",($event) => { if (badState) { $event.target.value = (+currentString); badState = false; document.getElementById("number").textContent = $event.target.value; } });
 #result{ padding: 10px; background-color: orange; font-size: 25px; width: 400px; margin-top: 10px; display: inline-block; } #field{ padding: 5px; border-radius: 5px; border: 1px solid grey; width: 400px; }
 <input type="number" id="field" keyup="keyUpFunction" step="0.01" placeholder="Field for both comma separators"> <span id="result" > <span >Current value: </span> <span id="number"></span> </span>

Angular 9 代碼段

 @Directive({ selector: '[appFloatHelper]' }) export class FloatHelperDirective { private currentString = ''; private badState = false; private lastCharacter: string = null; @HostListener("blur", ['$event']) onBlur(event) { if (this.badState) { this.model.update.emit((+this.currentString)); this.badState = false; } } constructor(private renderer: Renderer2, private el: ElementRef, private change: ChangeDetectorRef, private zone: NgZone, private model: NgModel) { this.renderer.listen(this.el.nativeElement, 'keyup', (e: KeyboardEvent) => { if (el.nativeElement.value && !el.nativeElement.validity.badInput) { this.currentString = el.nativeElement.value; } else if (el.nativeElement.validity.badInput) { if (this.badState && this.lastCharacter && this.lastCharacter.match(/[\\.,]/) && !isNaN(+e.key)) { model.update.emit((+this.currentString) + (+e.key / 10)); el.nativeElement.value = (+this.currentString) + (+e.key / 10); this.badState = false; } else { this.badState = true; } } this.lastCharacter = e.key; }); } }
 <input type="number" matInput placeholder="Field for both comma separators" appFloatHelper [(ngModel)]="numberModel">

我的推薦? 根本不要使用jQuery。 我和你有同樣的問題。 我發現$('#my_input').val()總是返回一些奇怪的結果。

嘗試使用document.getElementById('my_input').valueAsNumber而不是$("#my_input").val(); 然后,使用Number(your_value_retrieved)嘗試創建一個 Number。 如果值為 NaN,您當然知道這不是數字。

要添加的一件事是,當您在輸入上寫一個數字時,輸入實際上會接受幾乎任何字符(我可以寫歐元符號、美元和所有其他特殊字符),因此最好使用.valueAsNumber而不是使用 jQuery。

哦,順便說一句,這允許您的用戶添加國際化(即:支持逗號而不是點來創建十進制數)。 只需讓Number()對象為您創建一些東西,它就會是十進制安全的,可以這么說。

聽起來您想在數字輸入上使用 toLocaleString() 。

有關其用法,請參閱https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString

國際化(數字格式“num.toLocaleString()”)中也涵蓋了 JS 中數字的本地化不適用於 chrome

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM