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

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

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

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

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Q&A

3回答

5756閲覧

querySelectorAllで複数の要素を取得できない。

punchan36

総合スコア105

JavaScript

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

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

0グッド

0クリップ

投稿2021/07/16 07:48

編集2022/01/12 10:55

前提・実現したいこと

Ruby on Railsにて、複数の画像をアップロード出来るページ(users/edit.html.erb)を作成致しました。アップロードの機能自体は既に実装出来ています。

ここからこちらのページを参考に、選択されたファイルサイズが1MB以上である場合はアラートを表示させるコードを記述しました。

要素の取得にgetElementByIdを使った場合は問題なくアラートが表示されました。
ただ今回は画像が複数存在するためquerySelectorAllに変えて試してみたのですが、うまくアラートが表示されません。

該当のソースコード

アップロードしたい複数の画像に関する記述。

users/edit.html.erb

Rails

1<input name="image" type="file" accept=".png, .jpg, .jpeg, .gif" id="file_photo" class="file_photo" style="display:none;"> 2 3<input name="cover_image" type="file" accept=".png, .jpg, .jpeg, .gif" id="file_photo" class="file_photo2" style="display:none;">

以下はまずgetElementByIdで試したコードです。

file.js

js

1$(document).on('turbolinks:load', function () { 2 const sizeLimit = 1024 * 1024 * 1; 3 const fileInput = document.getElementById('file_photo'); // 問題の行。 4 const handleFileSelect = () => { 5 const files = fileInput.files; 6 for (let i = 0; i < files.length; i++) { 7 if (files[i].size > sizeLimit) { 8 alert('File size must be less than 1 MB.'); 9 fileInput.value = ''; 10 return; 11 } 12 } 13 } 14 fileInput.addEventListener('change', handleFileSelect); 15});

idは当然一つしか取得できませんので、一つ目の画像選択時にはアラートが表示されますが、二つ目の画像選択時にはアラートが表示されません。

次に他の記述はそのままに、問題の行のみquerySelectorAllに書き換えてみました。

file.js

js

1 const fileInput = document.querySelectorAll('.file_photo, .file_photo2'); // 問題の行。

しかし二つ目の画像どころか一つ目の方にもアラートが表示されなくなってしまいました。
どこかコードに間違いがありますでしょうか。どなたかご助言を頂けますと有難いです。

補足情報(FW/ツールのバージョンなど)

ruby 2.6.4p104
RubyGems 3.0.3
Rails 5.2.3
jquery 1.12.4

追記

ご指摘の通りidclassの使い方が逆になっておりましたので、下記の様に訂正いたします。

users/edit.html.erb

Rails

1<input name="image" type="file" accept=".png, .jpg, .jpeg, .gif" id="file_photo" class="file_photo" style="display:none;"> 2 3<input name="cover_image" type="file" accept=".png, .jpg, .jpeg, .gif" id="file_photo2" class="file_photo" style="display:none;">

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

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

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

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

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

guest

回答3

0

Document.querySelectorAll()は静的NodeListを返すので、取得後、forなどで1つずつ取り出す必要があります。

イメージ説明

リストが取れる点はgetElementsXXXX系(IdはgetElementなので違う)と同じです。

ただ、

jquery 1.12.4

jQuery入れてるなら要素取得はjQuery使われたほうが。
せっかく入れてるのに勿体ないですね。

投稿2021/07/16 07:56

編集2021/07/16 08:07
m.ts10806

総合スコア80765

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

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

0

ちょっと状況がわかりませんが、複数のHTML要素に同じIDを振るのをやめるところからでは?

投稿2021/07/16 07:53

yambejp

総合スコア114572

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

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

0

@yambejp さんおっしゃっているとおりで
id と class の使い方が逆だと思います。

document.getElementsByClassName で複数要素とれます。

js

1elems.forEach(elem => elem.addEventListener('change', handleFileSelect));

みたいな感じでそれぞれ EventListener の登録が必要です。

あと fileInput の中身をみて問題を切り分けるといいです。

投稿2021/07/16 08:05

anozon

総合スコア662

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

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

punchan36

2021/07/16 09:03

有難うございます。 getElementsByClassName にしても querySelectorAll にしても、要素を複数受け取った後はそれぞれ処理する必要があったのですね。 色々な方法があるようですが、一旦getElementsByClassNameを使ってトライしてみようと思います。 以下の様に記述を変えてみたのですがまだ上手くいきません。 追記致しましたように id と class の記述も変えた上で試しましたが、まだコードがおかしいでしょうか…。 $(document).on('turbolinks:load', function () { const sizeLimit = 1024 * 1024 * 1; const fileInput = document.getElementsByClassName('file_photo'); const handleFileSelect = () => { const files = fileInput.files; for (let i = 0; i < files.length; i++) { if (files[i].size > sizeLimit) { alert('File size must be less than 1 MB.'); fileInput.value = ''; return; } } } fileInput.forEach(elem => elem.addEventListener('change', handleFileSelect)); });
anozon

2021/07/16 09:23

handleFileSelect で 外側の fileInput を参照してしまっているので const handleFileSelect = (e) => { e.target.files // あいまい みたいな形でとれませんか?
punchan36

2021/07/17 13:46

有難うございます。 すみません、こう言う事でしょうか…思っていたよりも複雑で難しそうです。。 const fileInput = document.getElementsByClassName('file_photo'); const handleFileSelect = (e) => { const files = e.target.files;
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問