質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

解決済

6回答

5887閲覧

javascript input の中身をクレジットカード対応の4桁区切りにする

lyzmfeqpxs54

総合スコア237

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

1グッド

4クリップ

投稿2019/12/27 07:08

編集2019/12/27 07:12

いつもご回答ありがとうございます。

タイトル通りなのですが、フォームの中に設置したクレジット用のinputを、4桁入力されるたびに区切られるような方法を探しています。
inputは4つに分割せずに、1つのinputにしたく、4桁入力されるたびにスペースが入るようなものを想定しています。

html

1<input name="number" type="tel" placeholder="1234 5678 9012 3456" maxlength="16"> 2

ネットで調べてみても、海外のgiithubのjs関連ばかりが出てくるのですが、外部のjsを導入することなく、実現できるようなものをさがしております。

ご存知の方がいらっしゃいましたら、ご教示いただけますと幸いです。
よろしくお願いいたします。

DrqYuto👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Lhankor_Mhy

2019/12/27 07:16

「外部のjsを導入することなく」とは、具体的に言うとどういうことでしょうか?
lyzmfeqpxs54

2019/12/27 07:31

ご回答ありがとうございます。 言葉が足らず申し訳ございません。 ダウンロードして、フォルダにjsファイルを入れるという工程です。 SDN経由や、数十行程度であれば、html内の<script>にべた書きしたいと考えております。
maisumakun

2019/12/27 07:41

ダイナース(36**-******-****)やアメックス(37**-******-*****)の場合はどうしますか?
lyzmfeqpxs54

2019/12/27 07:43

その場合でも4桁区切りずつで問題ないと考えております。
Lhankor_Mhy

2019/12/27 07:50

> 数十行程度であれば minifyすれば1行になるかと思いますが、具体的には何バイト程度であれば許容可能ですか?
guest

回答6

0

フォームの中に設置したクレジット用のinputを、4桁入力されるたびに区切られるような方法を探しています。

そもそも論として、自分でクレジットカードを入力させるフォームを作ること自体、できれば避けたほうがいいです。自社のWebサイトに改ざんが入ると、そこからカード情報が漏洩する危険があります。

決済事業者のサイトに飛ばしてそちらで入力させる、という方式のほうがより安全です(参考)。

投稿2019/12/27 07:24

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lyzmfeqpxs54

2019/12/27 07:32

ご回答ありがとうございます。 決済にはPayjpを使用しており、その中のカスタムフォーム作成手順を用いて作成しております。 サブミット時にtoken化して送る流れなのですが、それでも問題がありますでしょうか。
maisumakun

2019/12/27 07:54 編集

あと、カード番号という扱いとは別件ですが、たとえば「1234」まで入力してフォームが「1234 」となったとします。 そこでバックスペースを押しても、自動入力されたスペースだけが消えて「1234」にしかならない、あるいは消しても自動入力がまた働いて「1234 」になってしまう、では入力しづらいことこの上ありません。 …というように、入力途中に文字を書き換えることと、まともな使い勝手を両立するのはけっこう煩雑になります。「見栄え」「操作性」「実装の手間」どれか1つは犠牲にしないといけないかと思います。 https://qiita.com/jkr_2255/items/f1c035fe6dee57518efe
guest

0

ベストアンサー

こんにちは

以下でどうでしょう?

html

1<input id='card-number-input' maxlength="19" />

javascript

1const regexp = /^(\d{1,4})?(\d{1,4})?(\d{1,4})?(\d{1,4})?$/; 2 3document 4 .getElementById('card-number-input') 5 .addEventListener('input', function(e) { 6 const digits = e.target.value.replace(/[^0-9]/g, ''); 7 e.target.value = [...regexp.exec(digits)].slice(1).filter(e => e).join(' '); 8 });

上記では、

  • 半角数字以外の文字(スペース含む。)が入力されても無視されます。
  • 途中まで入力した値をバックスペースで消していくときに、自動で追加された区切りのスペースは、自動的に消去されます。(※スペースを消すためのバックスペースを打つ必要がない、という意味です。)

参考になれば幸いです。

追記

上記の回答では、4桁ずつ区切るために正規表現を使いましたが、別の方法で区切るコードを挙げます。

「質問への追記・修正」のやりとりを拝読して、外部のモジュールも、場合によっては利用出来るということなのかなと思われました。以下は、 4桁ずつ区切るために、lodash の _.chunk を使ったコードです。

javascript

1document 2 .getElementById('card-number-input') 3 .addEventListener('input', function(e) { 4 const digits = e.target.value.replace(/[^0-9]/g, ''); 5 e.target.value = _.chunk(digits, 4).map(a => a.join('')).join(' '); 6 });

   

追記2

私の上記回答のコードだと、以下の手順で再現されるような不便さがありまして、実用に耐えうるものになっていないです。

  • input が空欄の状態から、1,2,3,4,5,6,7,8 と順に打つ。
  • 4の後ろにスペースが追加された 1234 5678 と表示される。
  • 3 を別の数字に修正するために、3 の後ろをクリックするか、矢印キーで、3の後ろにカーソルを移動させる。
  • バックスペースを押す
  • 表示が 1245 678 となり、かつ、カーソルが末尾(8 の後ろ)に移動してしまう。

上記の手順で、バックスペースを押した後の望ましい状態は、24の間にカーソルがあることですが、そのようになりません。これをきちんと制御するには、input のカーソル位置取得、設定をきめ細かくやる必要がありそうです。

投稿2019/12/27 09:12

編集2019/12/27 12:54
jun68ykt

総合スコア9058

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lyzmfeqpxs54

2019/12/27 14:03

ご回答ありがとうございます。 ご教示いただいたlodash.jsを読み込ませる方法が、一番動きの理想に近いものでした。 こちらを利用したいと思います。 こういった外部読み込みは全然探すことができず、お恥ずかしいです。 また何かありました際にご助言いただけましたら幸いです。 本当にありがとうございました。
jun68ykt

2019/12/27 14:16

どういたしまして。私の回答が、何らかヒントになれば幸いです。
Lhankor_Mhy

2019/12/27 16:04

外部jsを導入することなく、という条件は一体どうなったんだ…… いや、解決したのならそれはそれでいいのですけどね……?
guest

0

inputは4つに分割せずに、1つのinputにしたく、4桁入力されるたびにスペースが入るようなものを想定

change イベント内でフォーマット通りになるように矯正するしかなさそうですね。

StackOverflowにもご質問と同じ機能をjQueryで実装したい内容があり、回答としてJSFiddle がリンクされていました。

※入力様式を正規表現で矯正することで、期待する入力内容に整えることは可能です。


ちなみにですが、autocomplete で補完される様式を確認したことがあります。
区切りのない12桁の数字(テキストデータ)として補完されます。

ローカル環境でテストしたコード例(cc-number)

HTML

1<input type="text" id="num12" autocomplete="cc-number">

javascript

1let entryPoint = () =>{ 2 let field = document.querySelector("#num12"); 3 4 field.addEventListener("change", ()=>{ 5 console.log( field.value ); // 補完結果は「連続した12桁の数字」 6 }) 7} 8window.addEventListener("load", entryPoint);
  • [CodePen Home

Credit card autocomplete example](https://codepen.io/yuriyromadin/pen/KXGPyO) のようなテストを公開されている方もいます。

1つのINPUT要素で対応するには、「様式矯正」の手段しかなさそうです。

参考 MDN

ご参考になれば。

投稿2019/12/27 09:27

AkitoshiManabe

総合スコア5432

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

サンプル

html

1<input id="back"> 2<input id="fore">

css

1#back{ 2 position:absolute; 3} 4#fore{ 5 opacity:0; 6}

js

1var back = document.getElementById('back'); 2var fore = document.getElementById('fore'); 3fore.addEventListener('keyup',()=>{ 4 back.value = fore.value.split(/(.{4})/).filter(e=>e).join(' '); 5});

投稿2019/12/27 09:02

Lhankor_Mhy

総合スコア36074

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2019/12/27 09:08

カーソルが出ない、スペースが入る加減で狙った箇所と違うところにカーソルが入ってしまう、などがありますが、この発想もいいですね。
Lhankor_Mhy

2019/12/27 09:34

> スペースが入る加減で狙った箇所と違うところにカーソルが入ってしまう それは気がつかなかったです!
AkitoshiManabe

2019/12/27 09:56

正規表現のパターンに 「.{4}」が含まれるので、数字以外の入力(スペース含)を許容してます。
Lhankor_Mhy

2019/12/27 10:04

> 数字以外の入力(スペース含)を許容してます それが質問の要件に含まれているとは読みませんでしたが、ご意見は理解できますので低評価は受け入れます。
AkitoshiManabe

2019/12/27 10:19

> 質問の要件に含まれているとは読みませんでした 確かに質問欄での要件定義は曖昧ですよね。 質問へのコメントでのやり取りから、やっと「カード番号」なのだと確信できました。 あと、他に推したい回答がありましたので、粗探ししちゃいました。ごめんなさい。
guest

0

クレジットカードかどうかはセキュリティレベルが変わってくるので
一旦おいておきましょう

投稿2019/12/27 07:46

編集2019/12/27 07:47
yambejp

総合スコア114779

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2019/12/27 07:46

<script> window.addEventListener('DOMContentLoaded', ()=>{ document.querySelectorAll('[name="c[]"').forEach(x=>{ x.addEventListener('input',e=>{ var c=Array.from(x.parentNode.children).filter((l,m,n)=>{ return m>0 && n[m-1]==x; }); if(x.value.length==4 && c.length>0) c[0].focus(); }); }); }); </script> <input name="c[]" type="text" placeholder="1234" size="2" maxlength="4" required> <input name="c[]" type="text" placeholder="5678" size="2" maxlength="4" required> <input name="c[]" type="text" placeholder="9012" size="2" maxlength="4" required> <input name="c[]" type="text" placeholder="3456" size="2" maxlength="4" required>
lyzmfeqpxs54

2019/12/27 07:51

ご回答ありがとうございます。 ご回答いただいたのに大変恐縮なのですが、質問に書いた通りinputは4つに分割せずに、1つのinputにしたいと考えております。
Takumiboo

2019/12/27 07:57

それが何故か、を書いたほうがいいのでは?
lyzmfeqpxs54

2019/12/27 08:08

ご回答ありがとうございます。 依頼されている仕様がそのようになっているためです。
yambejp

2019/12/27 08:48 編集

やればやるほどユーザビリティが落ちそうですが例えばこう <script> window.addEventListener('DOMContentLoaded', ()=>{ document.querySelector('[name=c').addEventListener('input',e=>{ var t=e.target; var v=t.value; if(v.match(/[^\d ]|\d{5}| {2}|(^| )\d{1,3} /)){ v=v.replace(/[^\d]/g,""); v=v.replace(/(.{4})/g,"$1 "); v=v.replace(/(.{19}).+/g,"$1"); t.value=v; } }); }); </script> <input name="c" type="text" placeholder="1234 5678 9012 3456" maxlength="19" pattern="\d{4} \d{4} \d{4} \d{4}" required>
lyzmfeqpxs54

2019/12/27 14:06

度々のご回答本当にありがとうございます。 今回はlodash.jsを用いることにいたしましたが、ご教示いただいたコードもしっかり理解し、次へための勉強へ生かしたいと思います。
guest

0

こんな感じでしょうか?挙動はもう少し調整する必要がありますが。

JavaScript

1 const ele = document.getElementsByName("number")[0]; 2 ele.addEventListener("keypress", (event) => { 3 var str = event.target.value; 4 ele.value = str.replace( /(\d{4})(\d{1})/, '$1 $2' ); 5 });

投稿2019/12/27 07:56

編集2019/12/27 07:57
Masakin

総合スコア192

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問