【jQuery】複数の画像を選択し、選んだ画像を一覧で表示させる

　プログラミングの学習中に開発・実装したコードの復習で記事を書いていきます。
　自分の復習・アウトプットのため、また同様に学習中の同士に向けての記事となるよう意識しています。
　進める順序、考え方のみを記載しており、細かいコードや設定内容、数値はあえて記載していませんのでご了承ください。

## 画像をアップロードするためのフォーム作成
- 実装イメージ
<img width="651" alt="0c6cdaa410c76345368533231a34ed61.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495421/076b35af-b2df-319e-5b30-637939e45861.png">


　上のように、複数の画像をアップロードできるフォームを作成します。
実装までの大雑把な流れとしては、

1. HTML（HAML）でビュー作成
2. selectフォーム作成
3. jQuery実装

で進めていきました。

## HTML（HAML）でビュー作成

```new.html.haml
= form_for @item do |form|
  .sell__content
    .sell__image_label
      出品画像
      .sell__required
        必須
      .sell__text
        最大10枚までアップロードできます
      .sell__image_container#container

      .sell__upload--drop_box#dropbox
        .sell__upload--text
          ドラッグアンドドロップ
          %br
          またはクリックしてファイルをアップロード
        = form.file_field :image, id: :image1, multiple: true, class: :file_field
      .sell__number#number
        0
      .sell__number#total
        0
```

　HTMLの記述に関しては、例えばクラスの命名やブロックの数や構造などは各々の作りやすい、管理しやすい形にしていけばいいと思います。
ここでは今後の実装に際して気をつけた構造の部分を挙げていきます。

- jQueryのイベント発火用にwrapperを作成する(ここでは#container)

　名前をwrapperがらみでつける必要はないですが、jQueryのイベント発火をさせる際に都合がいいように選択画像を表示させる領域のボックスを用意しておいた方がいいです。理由は後述。

- 写真を選択した際に表示される、jsで動いたあとの静的ビューも作成しておく
<img width="656" alt="c0bc0c99be85e92bd8159f89166b1392.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495421/b2b71cd4-ddde-5345-092c-0fde36207436.png">

　上の画像は写真を2枚選択している状態のビューです。jsの実装前に、写真がアップロード前、1枚選択時、2枚選択時、・・・とビューを作っておきcssの設定数値を確認しておきます。これを確認しておかないと、js実装時に設定すべき数値が定まらずグダグダになってしまいます。

- 選択した画像の枚数、現在選択中の画像の枚数を参照できるようにする（ここでは#number, #totalの部分）


　これに関してもjsを実装させやすいようにするためのものです。正直美しくない形で実装しています。wrapperボックスのプロパティ（class名など）に入れておくと非常にスマートだと思われます。

　むしろビューで重要なのはcss側の設定であるような気もしますが、今回のメインではないので割愛します。
　あえて書くとするならば、selectフォームの幅と高さを100%、不透明度を0にしてクリックしたいボックスと重ねてしまうことです。ボックスをクリックしているつもりで選択フォームをクリックするようにしているということです。

## selectフォーム作成

<img width="258" alt="6fefbf1290811731ea5df025f38ce729.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495421/17f026c5-d6fe-716c-ff34-f059dabd80fe.png">

　先ほどのコードではすでにhaml内にfile_fieldを1つだけ追加していますが、本来複数の画像を選択（アップロード）するためには同数のファイル選択フォームが必要になります。
　しかし最初から10個のフォームを用意しておくと、途中で画像の削除などがあった場合に管理がしづらくなってしまいます。
　そのため画像を1枚選択する度に新しいフォームを作成するようにします。

## jQueryの実装

　複雑な実装になりそうですが、順を追って実装していけば難しくありません。実装していく機能としては、

- 画像を選択した時の機能
  - 画像が選択された時にイベント発火
  - 選択した画像の枚数、現在選択中の画像の枚数を変更(+1)
  - 選択した画像が表示されるボックスを作成、画像を表示
  - 新しい画像選択フォームを作成
  - 画像選択ボックスが小さくなるようcssを編集

- 選択した画像を削除する機能
  - 追加した画像の削除ボタンをクリックした時にイベント発火
  - 現在選択中の画像の枚数を変更（-1)
  - 表示した画像が選択されている画像選択フォームを削除
  - クリックしたターゲットを、親要素を含めて削除
  - 画像選択ボックスのcssを編集

　という流れになるかと思います。
　画像選択ボックスのcssは、現在選択中の画像枚数によって条件分岐させることで状況ごとの数値が適用されるようにします。
　画像を削除する機能についてですが、jQueryにより追加されたHTMLについては、直接jQueryイベント発火のターゲットと指定することができません。これは追加されたHTMLgaドキュメント読み込み（jQuery読み込み）の際になかったため、jQueryに認識されていないためです。
　そのため元々存在しているwrapper要素にフォーカスをあて、その中の要素を探させるようにする必要があります。しかしドキュメント全体から要素を探させると動作が重くなってしまうため、なるべく近くの部分にフォーカスをさせるようにしましょう。


　かなりざっくりとした実装までの流れですが、ある程度参考になれば嬉しいです。
　細かく実装したコードまで書いた方がいいかもしれないとは思いましたが、コードの丸写しになるよりもどのようなコードを書けばいいのか考えるキッカケになった方がいいなと思ったため大まかな流れだけにしました。
　どのように実装すればいいのか大まかにわかれば、具体的な書き方は自分なりに調べて書けると思いますし、正直それくらいしないと課題の意味がないと思われますので。
　正直なところ、小生も課題に追われておりブログ作成にそれほど時間をかけられないという現実もあります。年末年始が課題期間に入っているのでプライベートが忙しい状況ですので・・・。