วิธีจัดการการลอยตัวและตัวคั่นทศนิยมด้วยหมายเลขประเภทอินพุต html5


128

ฉันกำลังสร้างเว็บแอปซึ่งส่วนใหญ่สำหรับเบราว์เซอร์บนมือถือ ฉันใช้ช่องป้อนข้อมูลที่มีประเภทตัวเลขดังนั้นเบราว์เซอร์มือถือ (ส่วนใหญ่) จึงเรียกใช้แป้นพิมพ์ตัวเลขเท่านั้นเพื่อประสบการณ์การใช้งานที่ดีขึ้น เว็บแอปนี้ส่วนใหญ่จะใช้ในภูมิภาคที่ตัวคั่นทศนิยมเป็นลูกน้ำไม่ใช่จุดดังนั้นฉันต้องจัดการตัวคั่นทศนิยมทั้งสอง

จะปกปิดความยุ่งเหยิงทั้งหมดนี้ด้วยจุดและลูกน้ำได้อย่างไร

การค้นพบของฉัน:

Chrome บนเดสก์ท็อป

  • ประเภทอินพุต = หมายเลข
  • ผู้ใช้ป้อน "4,55" ในช่องป้อนข้อมูล
  • $("#my_input").val(); ส่งคืน "455"
  • ฉันไม่สามารถรับค่าที่ถูกต้องจากการป้อนข้อมูล

เดสก์ท็อป Firefox

  • ประเภทอินพุต = หมายเลข
  • ผู้ใช้ป้อน "4,55" ในช่องป้อนข้อมูล
  • $("#my_input").val(); ผลตอบแทน "4,55"
  • ไม่เป็นไรฉันสามารถแทนที่ลูกน้ำด้วยจุดและทำให้ค่าลอยถูกต้องได้

เบราว์เซอร์ Android

  • ประเภทอินพุต = หมายเลข
  • ผู้ใช้ป้อน "4,55" ในช่องป้อนข้อมูล
  • เมื่ออินพุตสูญเสียโฟกัสค่าจะถูกตัดให้เหลือ "4"
  • สร้างความสับสนให้กับผู้ใช้

Windows Phone 8

  • ประเภทอินพุต = หมายเลข
  • ผู้ใช้ป้อน "4,55" ในช่องป้อนข้อมูล
  • $("#my_input").val(); ผลตอบแทน "4,55"
  • ไม่เป็นไรฉันสามารถแทนที่ลูกน้ำด้วยจุดและทำให้ค่าลอยถูกต้องได้

"แนวทางปฏิบัติที่ดีที่สุด" ในสถานการณ์ประเภทนี้คืออะไรเมื่อผู้ใช้อาจใช้ลูกน้ำหรือจุดเป็นตัวคั่นทศนิยมและฉันต้องการให้ประเภทอินพุต html เป็นตัวเลขเพื่อมอบประสบการณ์การใช้งานที่ดีขึ้น

ฉันสามารถแปลงเครื่องหมายจุลภาคเป็นจุด "ทันที" เพื่อเชื่อมโยงเหตุการณ์สำคัญได้หรือไม่มันทำงานกับอินพุตตัวเลขได้หรือไม่

แก้ไข

Currenlty ฉันไม่มีวิธีแก้ปัญหาวิธีรับค่า float (เป็นสตริงหรือตัวเลข) จากอินพุตที่กำหนดประเภทเป็นตัวเลข หาก enduser ป้อน "4,55" Chrome จะส่งกลับ "455" เสมอ Firefox จะส่งคืน "4,55" ซึ่งก็ใช้ได้

นอกจากนี้มันค่อนข้างน่ารำคาญที่ใน Android (โปรแกรมจำลอง 4.2 ที่ทดสอบแล้ว) เมื่อฉันป้อน "4,55" ในช่องป้อนข้อมูลและเปลี่ยนโฟกัสไปที่อื่นหมายเลขที่ป้อนจะถูกตัดทอนเป็น "4"


ฉันเดาว่าสาเหตุของปัญหาบางอย่างของคุณคือเบราว์เซอร์ถูกตั้งค่าเป็นสถานที่ของสหรัฐอเมริกาซึ่งใช้จุดเป็นตัวคั่นทศนิยม ดูเหมือนว่า Chrome และ Android จะสับสนด้วยวิธีต่างๆกัน - Chrome ถือว่าลูกน้ำเป็นตัวคั่นหลักจากนั้นแปลงอินพุตเป็นตัวเลขจากนั้นแปลงเป็นสตริงอีกครั้ง.val()และ Android ก็ทำอะไรแปลก ๆ คุณสามารถตรวจสอบได้หรือไม่ว่าพวกเขาทำงานเหมือนกันเมื่อคุณตั้งค่าภาษาของระบบให้เหมาะสมหรือไม่?
มิลลิโมส

1
Nvm โพสต์สิ่งนี้เป็นคำตอบ
kjetilh

ดูเพิ่มเติมที่นี่: stackoverflow.com/a/24423879/196210
ย้อนหลัง

สถานการณ์เลวร้ายยิ่งกว่าที่คุณวาดไว้: คุณได้รับจุดทศนิยมหรือลูกน้ำบน WP numpad ขึ้นอยู่กับภาษาที่คุณเลือกใช้แป้นพิมพ์ นอกจากนี้ยังไม่มีวิธีค้นหาว่าเป็นภาษาที่ป้อนข้อมูลใด (ไม่จำเป็นต้องเป็นภาษาเบราว์เซอร์ที่ต้องการ) ... ดังนั้นสิ่งที่ดีที่สุดที่ฉันสามารถทำได้ (และสิ่งที่ดีพอสำหรับฉัน) คือ: var number = $(...).get(0).valueAsNumber; if (isNaN(number)) number = parseFloat($(...).val().replace(',', '.'); แต่วิธีแก้ปัญหานั้นใช้ได้เฉพาะเมื่อ ตัวเลขที่ใส่มีเพียง 1 ลูกน้ำและไม่มีจุดพิเศษ ...
bert bruynooghe

คำตอบ:


107

ผมคิดว่าสิ่งที่ขาดหายไปในคำตอบข้างต้นเป็นความจำเป็นที่จะระบุค่าที่แตกต่างกันสำหรับแอตทริบิวต์ที่มีค่าเริ่มต้นของ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: ตั้งเป็นแอตทริบิวต์เป็นค่าจุดลอยตัวเพราะมันเริ่มต้นที่step1

หมายเหตุ : ลูกน้ำไม่ได้ตรวจสอบความถูกต้องสำหรับฉัน แต่ฉันสงสัยว่าถ้าฉันตั้งค่าภาษา / ภูมิภาค OS ของฉันเป็นที่อื่นที่ใช้ลูกน้ำเป็นตัวคั่นทศนิยมมันจะใช้ได้ * หมายเหตุในหมายเหตุ *: นั่นไม่ใช่กรณีสำหรับการตั้งค่าภาษา / แป้นพิมพ์ของระบบปฏิบัติการ * เยอรมัน * ใน Ubuntu / Gnome 14.04


8
หากคุณต้องการอนุญาตให้มีทศนิยมหลายตำแหน่งโดยพลการให้ระบุstepแอตทริบิวต์"any"แทนเช่นเช่น"0.01"ที่แสดงไว้ที่นี่ ดูซอของ nathciketa เวอร์ชันปรับแต่งสำหรับการสาธิต
Mark Amery

4
ฉันยังวิ่งเข้าไปในปัญหาเกี่ยวกับการตรวจสอบเครื่องหมายจุลภาคไม่ได้ แต่ผมก็เดินเข้ามา "1,234.56" <input type="number" step="any">ลงใน ฉันไม่พบวิธีปิดการตรวจสอบ HTML5 ฉันสามารถปิดหรือปรับแต่งข้อความแสดงข้อผิดพลาดได้ แต่การดึงค่าจากข้อมูลที่ป้อนเข้ามานั้นเป็นเรื่องที่น่าเบื่อเสมอ ความคิดใด ๆ ?
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.รูปแบบจึงไร้ประโยชน์กับtype="number"
Michael Laffargue

เหมือนไมเคิลกล่าวว่าโปรดเปลี่ยนtypeไปtextมิฉะนั้นคำตอบของคุณจะทำให้รู้สึกไม่
phil294

23

ตาม W3.org ค่าแอตทริบิวต์ของใส่หมายเลขถูกกำหนดให้เป็นเลขทศนิยม ไวยากรณ์ของเลขทศนิยมดูเหมือนจะยอมรับเฉพาะจุดเป็นตัวคั่นทศนิยม

ฉันได้ระบุตัวเลือกสองสามรายการด้านล่างที่อาจเป็นประโยชน์สำหรับคุณ:

1. การใช้แอตทริบิวต์รูปแบบ

ด้วยแอตทริบิวต์รูปแบบคุณสามารถระบุรูปแบบที่อนุญาตด้วยนิพจน์ทั่วไปในวิธีที่เข้ากันได้กับ 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 (และ / หรือเบลอ ) ที่จะแทนที่เครื่องหมายจุลภาคหรือตรวจสอบความถูกต้องทั้งหมดเข้าด้วยกัน

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

2
input.valueAsNumber - ไม่มีความช่วยเหลือเนื่องจากใช้งานได้เฉพาะกับจุดเป็นตัวคั่นทศนิยมและในกรณีของฉัน enduser อาจใช้จุดหรือลูกน้ำ แท็กแบบฟอร์ม novalidate - ไม่พบผลกระทบใด ๆ ในเรื่องนี้
devha

น่าเสียดายที่ฉันไม่มีไอเดียดังนั้นฉันจึงไม่แน่ใจว่าคุณสามารถใช้งานข้ามเบราว์เซอร์นี้ได้หรือไม่โดยไม่มีวิธีแก้ปัญหา ฉันได้อัปเดตคำตอบของฉันเพื่อรวมแอตทริบิวต์รูปแบบแล้วฉันยังพบว่าสามารถใช้แอตทริบิวต์formnovalidateได้โดยตรงในช่องป้อนข้อมูล ฉันรู้ว่าคุณจะไม่ชอบ แต่ถ้าทุกอย่างล้มเหลวและคุณต้องใช้เครื่องหมายจุลภาคอย่างแน่นอนinput = "text"อาจเป็นทางเดียว ..
kjetilh

ดูเหมือนว่าหมายเลขประเภทอินพุตจะสร้างปัญหามากกว่าที่จะช่วยปรับปรุงประสบการณ์ของผู้ใช้ ในอุปกรณ์พกพามันจะดีมากถ้าฉันสามารถเปิดเฉพาะแป้นพิมพ์ตัวเลขให้กับผู้ใช้ถ้าฉันต้องการให้พวกเขาป้อนตัวเลขเท่านั้น อย่างไรก็ตามฉันต้องคิดใหม่อีกครั้ง ...
devha

เนื่องจากเราต้องรองรับการใช้ทั้งจุดและลูกน้ำเป็นตัวคั่นทศนิยมเราจึงวางแผนที่จะใช้รูปแบบสำหรับการตรวจสอบความถูกต้องบนเดสก์ท็อปร่วมกับ type = "text" จากนั้นเราจะเพิ่มคุณสมบัติการตรวจจับสำหรับการตรวจจับอุปกรณ์มือถือและใช้ type = "number" เมื่อมีการใช้งาน
กลัว

9

การใช้ลูกน้ำหรือจุดสำหรับตัวคั่นทศนิยมนั้นขึ้นอยู่กับเบราว์เซอร์ทั้งหมด เบราว์เซอร์ทำการตัดสินใจโดยพิจารณาจากสถานที่ของระบบปฏิบัติการหรือเบราว์เซอร์หรือบางเบราว์เซอร์ใช้คำแนะนำจากเว็บไซต์ ฉันสร้างแผนภูมิเปรียบเทียบเบราว์เซอร์ที่แสดงให้เห็นว่าเบราว์เซอร์ต่างๆรองรับวิธีการแปลที่แตกต่างกันอย่างไร Safari เป็นเบราว์เซอร์เดียวที่จัดการเครื่องหมายจุลภาคและจุดแทนกันได้

โดยพื้นฐานแล้วคุณในฐานะผู้เขียนเว็บไม่สามารถควบคุมสิ่งนี้ได้จริงๆ การแก้ไขปัญหาบางอย่างเกี่ยวข้องกับการใช้ช่องป้อนข้อมูลสองช่องที่มีจำนวนเต็ม สิ่งนี้ช่วยให้ผู้ใช้ทุกคนสามารถป้อนข้อมูลได้ตามที่คุณคาดหวัง มันไม่ได้เซ็กซี่เป็นพิเศษ แต่จะใช้ได้ผลกับผู้ใช้ทุกคน


7

ใช้valueAsNumberแทน.val().

อินพุต. valueAsNumber [= ค่า]

ส่งกลับตัวเลขที่แทนค่าของตัวควบคุมฟอร์มถ้ามี มิฉะนั้นจะคืนค่า null
สามารถตั้งค่าเพื่อเปลี่ยนค่า
แสดงข้อยกเว้น INVALID_STATE_ERR หากการควบคุมไม่ได้เป็นแบบวันที่หรือเวลาหรือตัวเลข


2
ปัญหาคือเขาต้องการสนับสนุนเครื่องหมายจุลภาคเป็นตัวคั่นทศนิยมและการใช้ type = "number" ในการป้อนข้อมูลทุกครั้งจะให้ตัวเลขที่ไม่ถูกต้องเมื่อเขียนลูกน้ำ
กลัว

ดูเหมือนว่าจะไม่ทำงานอย่างสม่ำเสมอบน Windows Phone NaNผลตอบแทนเสมอ
bert bruynooghe

@bertbruynooghe คุณกำหนดให้เป็นค่าอะไร?
Mike Samuel

ดูเหมือนจะไม่ได้ผลทั้งกับ '9', '9,1', '9.1' โทรศัพท์ได้รับการกำหนดค่าเป็น US รูปแบบแป้นพิมพ์ทดสอบ en-US, nl-BE
bert bruynooghe

4

ใช้ประเภทข้อความ แต่บังคับให้แสดงแป้นพิมพ์ตัวเลข

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

แท็ก inputmode คือทางออก


แต่ไม่สามารถใช้งานได้กับทุกเบราว์เซอร์เฉพาะกับ iOS Safari, Chrome, Chromium, Opera ... caniuse.com/#feat=input-inputmode เวอร์ชันล่าสุด :(
pgarciacamou

และนอกจากนี้คุณจะไม่ได้รับแป้นพิมพ์ตัวเลขนี้บนอุปกรณ์มือถือ
WoIIe

3

ฉันไม่พบโซลูชันที่สมบูรณ์แบบ แต่สิ่งที่ดีที่สุดที่ฉันทำได้คือใช้ type = "tel" และปิดใช้งานการตรวจสอบความถูกต้อง html5 (formnovalidate):

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

หากผู้ใช้ใส่เครื่องหมายจุลภาคระบบจะแสดงผลด้วยเครื่องหมายจุลภาคในเบราว์เซอร์สมัยใหม่ทุกตัวที่ฉันลองใช้ (FF, IE, edge, opera, chrome, เดสก์ท็อปซาฟารี, android chrome ล่าสุด)

ปัญหาหลักคือ:

  • ผู้ใช้มือถือจะเห็นแป้นพิมพ์โทรศัพท์ซึ่งอาจแตกต่างจากแป้นพิมพ์ตัวเลข
  • ที่แย่กว่านั้นแป้นพิมพ์โทรศัพท์อาจไม่มีปุ่มสำหรับลูกน้ำด้วยซ้ำ

สำหรับกรณีการใช้งานของฉันฉันต้อง:

  • แสดงค่าเริ่มต้นด้วยเครื่องหมายจุลภาค (firefox ขีดไว้สำหรับ type = number)
  • ไม่ล้มเหลวในการตรวจสอบความถูกต้อง html5 (หากมีเครื่องหมายจุลภาค)
  • ให้ฟิลด์อ่านตรงตามอินพุต (ด้วยเครื่องหมายจุลภาค)

หากคุณมีข้อกำหนดที่คล้ายกันสิ่งนี้ควรได้ผลสำหรับคุณ

หมายเหตุ:ฉันไม่ชอบการสนับสนุนของแอตทริบิวต์รูปแบบ formnovalidate ดูเหมือนจะทำงานได้ดีกว่ามาก


1

เมื่อคุณเรียก$("#my_input").val();มันกลับเป็นตัวแปรสตริง ดังนั้นใช้parseFloatและparseIntสำหรับการแปลง เมื่อคุณใช้parseFloatเดสก์ท็อปหรือโทรศัพท์ITSELFเข้าใจความหมายของตัวแปร

และนอกจากนี้คุณยังสามารถแปลง float เป็นสตริงได้โดยใช้toFixedอาร์กิวเมนต์ซึ่งมีจำนวนหลักดังนี้:

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

ไม่ทำงาน, ไม่เป็นผล. ลอง parseFloat ("1,5") ใน IE11 ผลตอบแทน 1. ภาษาเป็นภาษาเยอรมันสำหรับทั้ง OS และ IE
T3rm1

1

เห็นได้ชัดว่าเบราว์เซอร์ยังคงมีปัญหา (แม้ว่า Chrome และ Firefox Nightly จะทำได้ดี) ฉันมีวิธีแฮ็กสำหรับคนที่ต้องใช้ฟิลด์ตัวเลขจริงๆ (อาจเป็นเพราะลูกศรเล็ก ๆ ที่ช่องข้อความไม่มี)

โซลูชันของฉัน

ฉันเพิ่มตัวkeyupจัดการเหตุการณ์ลงในอินพุตแบบฟอร์มและติดตามสถานะและตั้งค่าเมื่อมันกลับมาถูกต้องอีกครั้ง

JS Snippet บริสุทธิ์ JSFIDDLE

Angular 9 Snippet


0

คำแนะนำของฉัน? อย่าใช้ jQuery เลย ฉันมีปัญหาเดียวกับคุณ ฉันพบว่ามัน$('#my_input').val()ให้ผลลัพธ์แปลก ๆ เสมอ

ลองใช้document.getElementById('my_input').valueAsNumberแทน$("#my_input").val();แล้วใช้Number(your_value_retrieved)เพื่อพยายามสร้างตัวเลข ถ้าค่าเป็น NaN คุณก็รู้แน่นอนว่านั่นไม่ใช่ตัวเลข

สิ่งหนึ่งที่ต้องเพิ่มคือเมื่อคุณเขียนตัวเลขบนอินพุตอินพุตจะยอมรับอักขระเกือบทุกตัว (ฉันสามารถเขียนเครื่องหมายยูโรดอลลาร์และอักขระพิเศษอื่น ๆ ทั้งหมดได้) ดังนั้นจึงเป็นการดีที่สุดที่จะดึงค่าโดยใช้.valueAsNumberแทนที่จะใช้ jQuery

โอ้และ BTW ที่ช่วยให้ผู้ใช้ของคุณสามารถเพิ่มความเป็นสากลได้ (เช่น: รองรับจุลภาคแทนจุดเพื่อสร้างตัวเลขทศนิยม) เพียงแค่ปล่อยให้Number()วัตถุสร้างบางสิ่งสำหรับคุณและมันจะปลอดภัยเป็นทศนิยมดังนั้นที่จะพูด


ปัญหาไม่ได้เกิดจาก jQuery และฉันพบว่าvalueAsNumberมันทำงานไม่สม่ำเสมอบนเบราว์เซอร์
bert bruynooghe

0

ดูเหมือนว่าคุณต้องการใช้ toLocaleString () กับอินพุตตัวเลขของคุณ

ดูhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleStringสำหรับการใช้งาน

การแปลตัวเลขใน JS ยังครอบคลุมในInternationalization (การจัดรูปแบบตัวเลข "num.toLocaleString ()") ไม่ทำงานสำหรับ chrome


2
เป็นเรื่องปกติที่จะให้คำอธิบายเพิ่มเติมเกี่ยวกับการแก้ปัญหาแม้ว่าคำตอบจะครอบคลุมเนื้อหาที่เชื่อมโยงอย่างครบถ้วนก็ตาม
IvanH

แนวทางนี้ดูเหมือนจะดีกว่าแนวทางอื่น ๆ หากเซิร์ฟเวอร์ส่วนหลังกำหนดโลแคลแทนที่จะเป็นเบราว์เซอร์เอง น่าเสียดายที่toLocaleStringไม่น่าเชื่อถือในทุกแพลตฟอร์ม
bert bruynooghe

สนับสนุนแพลตฟอร์มข้ามดูเหมือนกว้างพอกับผมในปี 2015 เห็นเช่นMozillas DevNet อย่างไรก็ตามหากคุณยังคงกังวลอยู่ให้ค้นหาวิธีแก้ไขที่เป็นไปได้ที่นี่
stackasec

Mozillas Devnet แทบจะไม่มีความเข้ากันได้สำหรับเบราว์เซอร์มือถือและนั่นคือสิ่งที่ช่องข้อความตัวเลขสามารถให้ประโยชน์สูงสุดได้ (ดูคำถามเดิม)
bert bruynooghe

... และมีการแสดงและอ้างอิงทางเลือกอื่น ๆ มากเกินพอ มีความสุข.
stackasec
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.