Quantcast
Channel: CSSタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8823

input type="file" をまともにする

$
0
0

ファイルアップロードのUI(input type="file")は厄介です。ブラウザによって表示方法が異なるのにCSSでのカスタマイズが難しいし、Chrome以外では添付したファイルをキャンセルできないという問題もあります。ですが、JavaScriptを使えば、

  1. CSSでカスタマイズ可能
  2. 添付したファイル名を表示可能
  3. 添付したファイルをキャンセル可能

にできます。

元のHTML

<formmethod="POST"enctype="multipart/form-data"><ul><li><inputtype="file"name="file1"></li><li><inputtype="file"name="file2"></li></ul><inputtype="submit"value="UPLOAD"></form>

input type="file"な要素が2つあります。なのでJavaScriptでコントロールするときには対象を特定する必要があります。

修正版HTML

よくあるのは input type="file"な要素を非表示にした上で label要素で囲み、labelのクリックで input type="file"のポップアップを連動させるというやり方です。ですが、JavaScript を使うのであれば labelにこだわる必要はありません。むしろ labelにはデフォルトで連動のアクションがあるため扱いが面倒です。

labelの代わりに spanで囲むことにします。目印のために class="upload"としています。

<formmethod="POST"enctype="multipart/form-data"><ul><li><spanclass="upload"><inputtype="file"name="file1"><inputdisabled></span></li><li><spanclass="upload"><inputtype="file"name="file1"><inputdisabled></span></li></ul><inputtype="submit"value="UPLOAD"></form>

spanの中には2つ input要素があります。一つは元々の input type="file"な要素、もう一つはファイル名を表示するために追加した要素です。追加した要素は表示のためだけに使うので、disabledにしています。アイコンなどを追加したい場合は span要素の中に入れればクリック時にポップアップと連動します。

追加のCSS

以下のCSSを追加します。

form.upload{display:inline-block;}form.uploadinput[type="file"]{display:none;}form.uploadinput[disabled]{pointer-events:none;}

span要素はクリックを「受け止める」必要があるため、inline-block にします。元々の input要素は非表示にし、追加した input要素はクリックを「素通し」するので pointer-events: none;とします。この設定がないと Firefox では追加した input要素がクリックを「消費」してしまい、spanまでクリックが伝わりません。

コントロール用JavaScript

以下のJavaScriptを追加します。

$(function(){$('.upload').on('click',function(){$(this).find('input').val('');$(this).find('input[type="file"]').trigger('click');});$('.upload input[type="file"]').on('click',function(event){event.stopPropagation();});$('.upload input[type="file"]').on('change',function(){if(this.files.length){$(this).parent().find('input[disabled]').val(this.files[0].name);}});});
  1. span要素(class="upload")がクリックされたときは、内部にある2つの input要素をともにクリアし、input type="file"な要素をクリックすることでポップアップを起動します。
  2. input type="file"な要素がクリックされたときに親要素へのイベント伝播を停止します。これを行わないと再度 spanがクリックされることになるので無限ループになってしまいます。
  3. ポップアップから戻ったとき、ファイルが選択されていればそのファイル名を追加した方の input要素に表示します。

jQueryを使ったので簡潔に書けました。生のDOM操作関数でも記述可能と思いますが、かなり面倒になると思います(私にはその根気はありません)。


Viewing all articles
Browse latest Browse all 8823

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>