Cách xử lý số float và dấu phân cách thập phân với số loại đầu vào html5


128

Tôi đang xây dựng ứng dụng web chủ yếu dành cho trình duyệt di động. Tôi đang sử dụng các trường đầu vào với loại số, vì vậy (hầu hết) các trình duyệt di động chỉ gọi bàn phím số để có trải nghiệm người dùng tốt hơn. Ứng dụng web này chủ yếu được sử dụng ở các khu vực có dấu tách thập phân là dấu phẩy, không phải dấu chấm, vì vậy tôi cần xử lý cả dấu tách thập phân.

Làm thế nào để che toàn bộ mớ hỗn độn này bằng dấu chấm và dấu phẩy?

Phát hiện của tôi:

Máy tính để bàn Chrome

  • Kiểu đầu vào = số
  • Người dùng nhập "4,55" vào trường nhập
  • $("#my_input").val(); trả về "455"
  • Tôi không thể nhận được giá trị chính xác từ đầu vào

Máy tính để bàn Firefox

  • Kiểu đầu vào = số
  • Người dùng nhập "4,55" vào trường nhập
  • $("#my_input").val(); trả về "4,55"
  • Đó là tốt, tôi có thể thay thế dấu phẩy bằng dấu chấm và có được float chính xác

Trình duyệt Android

  • Kiểu đầu vào = số
  • Người dùng nhập "4,55" vào trường nhập
  • Khi đầu vào mất tiêu điểm, giá trị bị cắt ngắn thành "4"
  • Nhầm lẫn với người dùng

Windows Phone 8

  • Kiểu đầu vào = số
  • Người dùng nhập "4,55" vào trường nhập
  • $("#my_input").val(); trả về "4,55"
  • Đó là tốt, tôi có thể thay thế dấu phẩy bằng dấu chấm và có được float chính xác

"Thực tiễn tốt nhất" trong loại tình huống này là gì khi người dùng có thể sử dụng dấu phẩy hoặc dấu chấm làm dấu tách thập phân và tôi muốn giữ loại đầu vào html dưới dạng số, để cung cấp trải nghiệm người dùng tốt hơn?

Tôi có thể chuyển đổi dấu phẩy thành dấu chấm "đang hoạt động", ràng buộc các sự kiện chính, nó có hoạt động với đầu vào số không?

BIÊN TẬP

Currenlty Tôi không có bất kỳ giải pháp nào, làm thế nào để có được giá trị float (dưới dạng chuỗi hoặc số) từ đầu vào loại nào được đặt thành số. Nếu enduser nhập "4,55", Chrome luôn trả về "455", Firefox trả về "4,55" là ổn.

Ngoài ra, điều khá khó chịu là trong Android (trình giả lập 4.2 đã được thử nghiệm), khi tôi nhập "4,55" vào trường nhập và thay đổi tiêu điểm sang một nơi khác, số đã nhập bị cắt ngắn thành "4".


Tôi đoán là nguyên nhân cốt lõi của một số vấn đề của bạn là các trình duyệt được đặt thành ngôn ngữ Hoa Kỳ sử dụng dấu chấm làm dấu phân cách thập phân. Có vẻ như Chrome và Android đang bị nhầm lẫn bởi điều này theo những cách khác nhau - Chrome coi dấu phẩy là dấu tách chữ số, sau đó chuyển đổi đầu vào thành số, sau đó chuyển đổi lại thành chuỗi .val()và Android làm điều gì đó kỳ lạ. Bạn có thể kiểm tra xem chúng có hoạt động giống nhau không khi bạn đặt ngôn ngữ hệ thống thành thứ gì đó phù hợp?
millimoose

1
Nvm đăng bài này như một câu trả lời
kjetilh


Tình huống thậm chí còn tồi tệ hơn bạn mô tả: bạn nhận được dấu thập phân hoặc dấu phẩy trên bàn phím WP tùy thuộc vào ngôn ngữ bạn chọn bàn phím để làm việc. Cũng không có cách nào để tìm ra ngôn ngữ đầu vào (không nhất thiết phải là ngôn ngữ trình duyệt ưa thích) ... Vì vậy, điều tốt nhất tôi có thể đưa ra (và điều gì đủ tốt cho tôi) là: var number = $(...).get(0).valueAsNumber; if (isNaN(number)) number = parseFloat($(...).val().replace(',', '.'); Nhưng giải pháp đó chỉ hoạt động nếu số đã được đặt chỉ chứa 1 dấu phẩy và không có dấu chấm thừa ...
bert bruynooghe

Câu trả lời:


107

Tôi nghĩ những gì còn thiếu trong các câu trả lời ở trên là cần chỉ định một giá trị khác cho stepthuộc tính, có giá trị mặc định là 1. Nếu bạn muốn thuật toán xác thực của đầu vào cho phép các giá trị dấu phẩy động, chỉ định một bước tương ứng.

Ví dụ: tôi muốn số tiền đô la, vì vậy tôi đã chỉ định một bước như thế này:

 <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.">

Không có gì sai khi sử dụng jQuery để lấy giá trị, nhưng bạn sẽ thấy hữu ích khi sử dụng API DOM trực tiếp để lấy thuộc tính của các thành phần validity.valid.

Tôi có một vấn đề tương tự với dấu thập phân, nhưng lý do tôi nhận ra có một vấn đề là do kiểu dáng mà Twitter Bootstrap thêm vào một đầu vào số có giá trị không hợp lệ.

Đây là một câu đố chứng minh rằng việc thêm stepthuộc tính làm cho nó hoạt động và cũng kiểm tra xem giá trị hiện tại có hợp lệ hay không:

TL; DR: Đặt stepthuộc tính thành giá trị dấu phẩy động, vì nó mặc định là 1.

LƯU Ý : Dấu phẩy không xác thực cho tôi, nhưng tôi nghi ngờ rằng nếu tôi đặt cài đặt ngôn ngữ / vùng của hệ điều hành của mình thành một nơi sử dụng dấu phẩy làm dấu tách thập phân, nó sẽ hoạt động. * lưu ý trong ghi chú *: đó không phải là trường hợp cài đặt ngôn ngữ / bàn phím hệ điều hành * Tiếng Đức * trong Ubuntu / Gnome 14.04.


8
Nếu bạn muốn cho phép tùy ý nhiều vị trí thập phân, chỉ định stepthuộc tính "any"thay vì ví dụ "0.01"như được hiển thị ở đây. Xem phiên bản tinh chỉnh này của fath nathciketa để xem bản demo.
Đánh dấu Amery

4
Tôi cũng gặp vấn đề với dấu phẩy không xác thực, mặc dù tôi đã nhập "1,234,56" vào <input type="number" step="any">. Tôi chưa thể tìm cách tắt xác thực HTML5. Tôi có thể tắt hoặc tùy chỉnh thông báo lỗi, nhưng việc truy xuất giá trị từ đầu vào luôn luôn là một crapshoot. Có ý kiến ​​gì không?
Nick G.

5
This attribute applies when the value of the type attribute is text, search, tel, url, email, or password, otherwise it is ignored.Vì vậy, mô hình là vô dụng vớitype="number"
Michael Laffargue

như michael đã nói, xin vui lòng thay đổi typethành text, nếu không câu trả lời của bạn không có ý nghĩa.
phil294

23

Theo w3.org, thuộc tính giá trị của đầu vào số được định nghĩa là số dấu phẩy động . Cú pháp của số dấu phẩy động dường như chỉ chấp nhận dấu chấm dưới dạng dấu phân cách thập phân.

Tôi đã liệt kê một vài tùy chọn bên dưới có thể hữu ích cho bạn:

1. Sử dụng thuộc tính mẫu

Với thuộc tính mẫu, bạn có thể chỉ định định dạng được phép bằng biểu thức chính quy theo cách tương thích với HTML5. Ở đây bạn có thể chỉ định rằng ký tự dấu phẩy được cho phép và một thông báo phản hồi hữu ích nếu mẫu không thành công.

<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."/>

Lưu ý: Hỗ trợ nhiều trình duyệt khác nhau rất nhiều. Nó có thể hoàn chỉnh, một phần hoặc không tồn tại ..

2. Xác thực JavaScript

Bạn có thể cố gắng liên kết một cuộc gọi lại đơn giản để ví dụ sự kiện onchange (và / hoặc làm mờ ) sẽ thay thế dấu phẩy hoặc xác thực tất cả cùng nhau.

3. Vô hiệu hóa xác thực trình duyệt ##

Thứ ba, bạn có thể thử sử dụng thuộc tính formnovalidate trên các đầu vào số với mục đích vô hiệu hóa xác thực trình duyệt cho trường đó cùng nhau.

<input type="number" formnovalidate />

4. Kết hợp ..?

<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."/>

2
input.valueAsNumber - Không có trợ giúp vì điều này chỉ hoạt động với các dấu chấm như dấu tách thập phân và trong trường hợp của tôi, enduser có thể sử dụng dấu chấm hoặc dấu phẩy. Thẻ mẫu novalidate - Không tìm thấy bất kỳ ảnh hưởng nào đến việc này.
devha

Thật không may, tôi đang cạn kiệt ý tưởng, vì vậy tôi không chắc liệu bạn có thể thực hiện công việc này trên nhiều trình duyệt mà không có giải pháp khắc phục hay không. Tôi đã cập nhật câu trả lời của mình để bao gồm thuộc tính mẫu Tôi cũng thấy người ta có thể sử dụng thuộc tính formnovalidate trực tiếp trên các trường đầu vào. Tôi biết bạn sẽ không thích nó nhưng nếu mọi thứ thất bại và bạn hoàn toàn cần dấu phẩy thì input = "text" có thể là cách duy nhất ..
kjetilh

Có vẻ như số loại đầu vào tạo ra nhiều vấn đề hơn là thực sự cải thiện trải nghiệm người dùng. Trong thiết bị di động, thật tuyệt nếu tôi chỉ có thể mở bàn phím số cho người dùng nếu tôi muốn họ chỉ nhập số. Dù sao, tôi cần phải suy nghĩ lại điều này một lần nữa ...
devha

Vì chúng tôi cũng cần hỗ trợ sử dụng cả dấu chấm và dấu phẩy làm dấu tách thập phân, chúng tôi dự định sử dụng mẫu để xác thực trên máy tính để bàn kết hợp với loại = "văn bản". Sau đó, chúng tôi sẽ thêm tính năng phát hiện để phát hiện thiết bị di động và sử dụng loại = "số" khi áp dụng.
kinh ngạc

9

Việc sử dụng dấu phẩy hay dấu chấm cho dấu tách thập phân hoàn toàn tùy thuộc vào trình duyệt. Trình duyệt đưa ra quyết định dựa trên ngôn ngữ của hệ điều hành hoặc trình duyệt hoặc một số trình duyệt đưa ra gợi ý từ trang web. Tôi đã tạo một biểu đồ so sánh trình duyệt cho thấy các trình duyệt khác nhau hỗ trợ xử lý các phương thức bản địa hóa khác nhau như thế nào. Safari là trình duyệt duy nhất xử lý dấu phẩy và dấu chấm thay thế cho nhau.

Về cơ bản, bạn là một tác giả web không thể thực sự kiểm soát điều này. Một số công việc liên quan đến việc sử dụng hai trường đầu vào với số nguyên. Điều này cho phép mọi người dùng nhập dữ liệu như bạn mong đợi. Nó không đặc biệt gợi cảm, nhưng nó sẽ hoạt động trong mọi trường hợp cho tất cả người dùng.


7

Sử dụng valueAsNumberthay vì .val().

đầu vào . valueAsNumber [= value]

Trả về một số đại diện cho giá trị của điều khiển biểu mẫu, nếu có; nếu không, trả về null.
Có thể được đặt, để thay đổi giá trị.
Ném một ngoại lệ INVALID_STATE_ERR nếu điều khiển không dựa trên ngày hoặc thời gian cũng không phải là số.


2
Vấn đề là anh ta muốn hỗ trợ dấu phẩy dưới dạng dấu tách thập phân và sử dụng type = "number" trên các đường dẫn đầu vào sẽ đưa ra số không hợp lệ khi viết dấu phẩy.
kinh ngạc

Có vẻ như không hoạt động nhất quán trên Windows Phone; luôn luôn trở về NaN.
bert bruynooghe 4/2/2015

@bertbruynooghe, bạn đang gán giá trị gì?
Mike Samuel

Dường như không hoạt động, với '9', '9,1', '9.1'. Điện thoại được cấu hình là US, bố trí bàn phím được thử nghiệm en-US, nl-BE.
bert bruynooghe 6/2/2015

4

sử dụng một loại văn bản nhưng buộc sự xuất hiện của bàn phím số

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

thẻ inputmode là giải pháp


Nhưng nó không tương thích với tất cả các trình duyệt, chỉ với các phiên bản iOS Safari, Chrome, Chromium, Opera ... caniuse.com/#feat=input-inputmode mới nhất :(
pgarciacamou

Ngoài ra, bạn không có bàn phím số gọn gàng này trên thiết bị di động.
WoIIe

3

Tôi chưa tìm thấy một giải pháp hoàn hảo nhưng cách tốt nhất tôi có thể làm là sử dụng type = "tel" và vô hiệu hóa xác thực html5 (formnovalidate):

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

Nếu người dùng đặt dấu phẩy, nó sẽ xuất ra dấu phẩy trong mọi trình duyệt hiện đại mà tôi đã thử (FF, IE, edge, opera, chrome, safari desktop, android chrome).

Vấn đề chính là:

  • Người dùng di động sẽ thấy bàn phím điện thoại của họ có thể khác với bàn phím số.
  • Thậm chí tệ hơn bàn phím điện thoại thậm chí có thể không có phím cho dấu phẩy.

Đối với trường hợp sử dụng của tôi, tôi chỉ phải:

  • Hiển thị giá trị ban đầu bằng dấu phẩy (firefox loại bỏ giá trị cho loại = số)
  • Không thất bại xác thực html5 (nếu có dấu phẩy)
  • Có trường đọc chính xác như đầu vào (với dấu phẩy có thể)

Nếu bạn có một yêu cầu tương tự, điều này sẽ làm việc cho bạn.

Lưu ý: Tôi không thích sự hỗ trợ của thuộc tính mẫu. Formnovalidate dường như hoạt động tốt hơn nhiều.


1

Khi bạn gọi $("#my_input").val();nó trả về dưới dạng biến chuỗi. Vì vậy, sử dụng parseFloatparseIntđể chuyển đổi. Khi bạn sử dụng parseFloatmáy tính để bàn hoặc điện thoại ITSELF hiểu ý nghĩa của biến.

Và ngoài ra, bạn có thể chuyển đổi một chuỗi float thành chuỗi bằng cách sử dụng toFixedđối số đếm các chữ số như dưới đây:

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

Không hoạt động. Hãy thử parseFloat ("1,5") trong IE11. Trả về 1. Ngôn ngữ là tiếng Đức cho cả HĐH và IE.
T3rm1

1

Trình duyệt xuất hiện vẫn gặp sự cố (mặc dù Chrome và Firefox Nightly hoạt động tốt). Tôi có một cách tiếp cận khó khăn cho những người thực sự phải sử dụng một trường số (có thể vì những mũi tên nhỏ mà trường văn bản không có).

Giải pháp của tôi

Tôi đã thêm một keyup lý sự kiện vào đầu vào biểu mẫu và theo dõi trạng thái và đặt giá trị một khi nó trở lại hợp lệ.

Đoạn thuần túy JSFIDDLE

Đoạn 9 góc


0

Đề nghị của tôi? Đừng sử dụng jQuery. Tôi đã có vấn đề tương tự như bạn. Tôi thấy rằng$('#my_input').val() luôn luôn trả lại một số kết quả kỳ lạ.

Cố gắng sử dụng document.getElementById('my_input').valueAsNumberthay vì $("#my_input").val();và sau đó, sử dụngNumber(your_value_retrieved) để cố gắng tạo Số. Nếu giá trị là NaN, bạn chắc chắn đó không phải là số.

Một điều cần thêm là khi bạn viết một số trên đầu vào, đầu vào thực sự sẽ chấp nhận hầu hết mọi ký tự (tôi có thể viết ký hiệu euro, đô la và tất cả các ký tự đặc biệt khác), vì vậy tốt nhất là lấy giá trị bằng cách sử dụng .valueAsNumberthay vì sử dụng jQuery.

Ồ, và BTW, cho phép người dùng của bạn thêm quốc tế hóa (nghĩa là: hỗ trợ dấu phẩy thay vì dấu chấm để tạo số thập phân). Chỉ cần để Number()đối tượng tạo ra một cái gì đó cho bạn và nó sẽ an toàn thập phân, có thể nói như vậy.


Vấn đề không phải do jQuery gây ra và tôi thấy valueAsNumbercũng không hoạt động ổn định trên các trình duyệt.
bert bruynooghe 4/2/2015

0

Âm thanh như bạn muốn sử dụng toLocaleString () trên các đầu vào số của bạn.

Xem https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString để biết cách sử dụng.

Bản địa hóa các số trong JS cũng được đề cập trong Quốc tế hóa (Định dạng số "num.toLocaleString ()") không hoạt động cho chrome


2
Thông thường sẽ đưa ra giải thích thêm về giải pháp ngay cả khi câu trả lời nếu được bao phủ đầy đủ bởi nội dung được liên kết.
IvanH

Cách tiếp cận này có vẻ tốt hơn các cách tiếp cận khác nếu máy chủ phía sau đang xác định miền địa phương chứ không phải chính trình duyệt. Thật không may, toLocaleStringkhông đáng tin cậy trên các nền tảng.
bert bruynooghe 4/2/2015

Hỗ trợ đa nền tảng có vẻ đủ rộng đối với tôi trong năm 2015, xem ví dụ Mozillas Devnet . Tuy nhiên, nếu nó vẫn còn là mối quan tâm của bạn, hãy tìm giải pháp khả thi tại đây.
stackasec

Mozillas Devnet cho thấy hầu như không tương thích với các trình duyệt di động và đó chính xác là nơi mà văn bản số có thể mang lại nhiều lợi ích nhất. (Xem câu hỏi ban đầu.)
bert bruynooghe

... Và hơn đủ các lựa chọn thay thế đã được hiển thị và tham chiếu. Chúc vui vẻ.
stackasec
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.