検索
リンク
タグ
ASP.NET
.NET
ASP.NET MVC
F#
Azure
Visual Studio
ASP.NET Core
ライトニングトーク
Plone
Selenium
AJAX
C#
jQuery
ADO.NET Entity Framework
JavaScript
SQL Server
EFCore
LINQ
WebMatrix
Fizz-Buzz
カテゴリ
最新の記事
最新のコメント
記事ランキング
最新のトラックバック
以前の記事
2024年 02月 2024年 01月 2023年 12月 2023年 11月 2023年 10月 2023年 09月 2023年 08月 2023年 07月 2023年 06月 2023年 05月 2023年 04月 2023年 03月 2023年 02月 2023年 01月 2022年 12月 2022年 11月 2022年 10月 2022年 09月 2022年 08月 2022年 07月 2022年 06月 2022年 05月 2022年 04月 2022年 03月 2022年 02月 2022年 01月 2021年 12月 2021年 11月 2021年 10月 2021年 09月 2021年 08月 2021年 07月 2021年 06月 2021年 05月 2021年 04月 2021年 03月 2021年 02月 2021年 01月 2020年 12月 2020年 11月 2020年 10月 2020年 09月 2020年 08月 2020年 07月 2020年 06月 2020年 05月 2020年 04月 2020年 03月 2020年 02月 2020年 01月 2019年 12月 2019年 11月 2019年 10月 2019年 09月 2019年 08月 2019年 07月 2019年 06月 2019年 05月 2019年 04月 2019年 03月 2019年 02月 2019年 01月 2018年 12月 2018年 11月 2018年 10月 2018年 09月 2018年 08月 2018年 07月 2018年 06月 2018年 05月 2018年 04月 2018年 03月 2018年 02月 2018年 01月 2017年 12月 2017年 11月 2017年 10月 2017年 09月 2017年 08月 2017年 07月 2017年 06月 2017年 05月 2017年 04月 2017年 02月 2017年 01月 2016年 12月 2016年 11月 2016年 10月 2016年 09月 2016年 08月 2016年 07月 2016年 06月 2016年 05月 2016年 04月 2016年 03月 2016年 02月 2016年 01月 2015年 12月 2015年 11月 2015年 10月 2015年 09月 2015年 08月 2015年 07月 2015年 05月 2015年 04月 2015年 03月 2015年 02月 2015年 01月 2014年 12月 2014年 11月 2014年 10月 2014年 09月 2014年 08月 2014年 06月 2014年 04月 2014年 03月 2014年 02月 2014年 01月 2013年 12月 2013年 10月 2013年 09月 2013年 08月 2013年 07月 2013年 06月 2013年 05月 2013年 04月 2013年 03月 2013年 02月 2013年 01月 2012年 12月 2012年 11月 2012年 10月 2012年 09月 2012年 08月 2012年 07月 2012年 06月 2012年 05月 2012年 04月 2012年 03月 2012年 02月 2012年 01月 2011年 12月 2011年 11月 2011年 10月 2011年 09月 2011年 08月 2011年 07月 2011年 06月 2011年 05月 2011年 04月 2011年 03月 2011年 02月 2011年 01月 2010年 12月 2010年 11月 2010年 10月 2010年 09月 2010年 08月 2010年 07月 2010年 06月 2010年 05月 2010年 04月 2010年 03月 2010年 02月 2010年 01月 2009年 12月 2009年 10月 2009年 09月 2009年 07月 2009年 06月 2009年 05月 2009年 04月 2009年 03月 2009年 02月 2009年 01月 2008年 12月 2008年 11月 2008年 10月 2008年 09月 2008年 08月 2008年 07月 2008年 06月 2008年 05月 2008年 04月 2008年 03月 2008年 02月 2008年 01月 2007年 12月 2007年 11月 2007年 04月 2007年 03月 2007年 02月 2007年 01月 2006年 11月 2006年 10月 2006年 09月 2006年 08月 2006年 07月 |
2012年 09月 23日
input:file 要素じゃないのにファイルアップロード?なにはともあれ、下記 Web サイトで動作をお試しいただきたい。https://fileuploadsample.apphb.com/ 「Upload image...」と書かれたボタンをクリックすると、ファイル選択のダイアログが表示されるはずだ。 そこで .png や .jpg 等、適当な画像ファイルを選択してOKすると、即アップロードが始まる。 アップロードが完了すると、そのアップロードした画像をそのままページ上に表示する、そういうアプリになっている。 ※画像以外のファイルもアップロードできてしまうが、あくまでサンプルなので、画像以外がUpされた場合の対処とかは行っていない。ご勘弁を。 ※アップロードした画像はどこにも保存はしていない。そのアップロード結果のページを生成するときに img 要素の data uri を生成しているだけである。 この Web サイトのポイントは、Adobe Flash や Microsoft Silverlight、Java などのプラグインを使うことなく、ごくごく単純な input type="file" 要素を使ったフォーム送信に過ぎない点。 実際、ソースコードをみるとわかるが、input type="file" 要素は実在している。 にもかかわらず、 表示上、input type="file" 要素が見えない ように作られている。 さて、このようなファイルアップロードの UI をどう作るか? というのが今回のお題。 まずは普通にファイルアップロードのフォームを作るまずは開始地点として、ごくごく普通に、form 要素内に input type=file 要素と input type=submit 要素を配置して、どうということのないファイルアップロードのフォームを構築する。強いて言えば、form 要素の enctype 属性に "multipart/form-data" を指定することを忘れずに、というくらいか。 ファイル選択されたら即アップロード開始次に JavaScript を使って、ファイルが選択されたら、それ以上のユーザー操作は無用として、即アップロードを実施するよう配線する。input type=file 要素は、ファイル選択ダイアログが開かれて、なにかファイルが正しく選択されてOKボタンでファイル選択ダイアログが閉じられると、change DOM イベントが発火する。 つまり、JavaScript コードにて、input type=file 要素の change イベントをハンドル、そのハンドラ内で form 要素の submit() メソッドを呼べばよい。 input:submit がクリックされたらファイル選択ダイアログを開く最後に、input type=submit 要素がクリックされたら、input type=file 要素によるファイル選択ダイアログが開くように、JavaScript コードで配線する。これはどうということはない、input type=submit 要素の click イベントハンドラで、input type=file 要素の click メソッドを呼んでやるだけだ。 もっとも、input type=submit 要素それ自身の click 操作はキャンセルして、 form 送信が発生しないようにする点は注意。 ※実際のところ、ここまで作りこみした時点では、input type=submit 要素である必要はもうない。 click イベントを受け取れる可視要素ならなんでもいい。 とはいえ、コードを変更していった変遷を追うには便利なので、このまま input type=submit 要素を使ったまま話を進める。 あとは input type=file 要素の CSS 属性指定で display:none を指定して、input type=file 要素を見た目上隠してしまえば完成だ。 ところが IE では機能しないところがこの実装、実際に試してみると、Internet Explorer (8~10) では正常に動作しない。input type=submit 要素をクリックすると、input type=file 要素によるファイル選択ダイアログが表示され、ファイル選択したら form 送信が発動するのは IE でも変わらない。 しかし、IE の場合は、実際に form 送信された内容の内、input type=file の内容が空なのだ。 どうも、IE のセキュリティ上の都合か制限か、とにかくそういうことらしい。 別の方法 - input:file をボタンの上に重ねるということで、IE にも対応すべく、別の方法を考案する。「input type=file 要素を input type=submit 要素の手前に重ねて配置して、 type=submit をクリックしたつもりが、type=file をクリックしたことになる」という作戦だ。 「参照...」ボタンを大きく具体的には、まず、input type=file 要素の「参照...」ボタンを確実にクリックしてもらえるようにするため、この「参照...」ボタンをおもいっきり大きくする。高さは CSS の height 属性で適当に300pxとか指定すれば十二分だろう。 ところが幅は曲者。 CSS の width 属性で大きなサイズを指定しても、選択したファイル名の表示欄が伸びるだけある。 「参照...」ボタンの幅は変わらないのだ。 そこで CSS の width 属性ではなく、font-size 属性を使う。 font-size:300px とか指定するわけだ。 こうすることで、「参照...」ボタンのサイズを大きくすることができる。 input:file 要素を、所定のサイズにクリッピング次の手順は、大きくなった input type=file 要素を、ボタンのサイズにクリッピングする。input type=file 要素を囲む div 要素を用意し、この div 要素の CSS 指定で、 overflow: hidden を指定する。 こうすることで所定の大きさをはみ出た input type=file 要素の部分は、親要素の div 要素の枠で切り取られる格好となる。 input:file の右端を、クリッピング領域の右端にただしこれだけでは、親の div 要素内には、input type=file 要素の左端が見えているわけであり、ここをクリックしても、選択したファイル名の表示欄にキャレットが入るだけである。なので、input type=file 要素の右端を、親の div 要素の右端に合わせる必要がある。 そのために、この時点で、input type=file 要素の CSS の position 属性を absolute にしてしまう。 いずれにせよ、input type=submit 要素の前面に重ねるので position:absolute 指定が必要になるのだ。 ここで親の div 要素の CSS position 属性を static 以外にするのがポイント。 position:absolute な要素は、親要素の CSS position 属性が static 以外の場合は、top や left などの座標指定は、ブラウザウィンドウの絶対座標ではなく、親要素に対する相対座標として機能することになる。 今回は、親の div 要素はブロック要素ないしはインラインブロック要素として扱うことを想定し、親の div 要素には CSS position:relative を指定した。 以上で、input type=file 要素は、親の div 要素が実際に配置される位置にぴったり追随するようになる。 さらに input type=file 要素の CSS right 属性を 0 に指定することで、 input type=file 要素の右端が、親の div 要素の右端にくっつくようになる。 input:submit の前面に、input:file を重ねて、透明にあとは input type=file 要素の親の div 内に、input tyep=submit 要素も配置、さらに親の div 要素と input type=submit 要素の高さと幅を CSS でぴったり同じに指定することで、input type=file 要素 (の「参照...」ボタン部分) が、input type=submit 要素の前面に覆いかぶさるように配置されることになる。最後の仕上げとして、input type=file 要素の透明度を 0.01 などに指定して、透明に指定してやればできあがりだ。 Firefox の 3D ビューなどで確認すると、クリップされていたが実は巨大な input type=file 要素や、その下敷きに input type=submit 要素がいることが窺える。 弱点・補足表示上見えている input type=submit 要素は、実際には押されることはない。そのため、どんなにマウスでクリックしても、ペコペコへこまないのが難点。 ブラウザ・OS ネイティブのボタンコントロールの容姿にせずに、独自にデザインしてやったほうがよさそうである。 そのような目的で、タイル状のボタンデザインにする場合は、今度はマウスホバーに反応して色を明るく表示するなどの表示効果を与えて、ユーザーへのフィードバックを実現すべきであろう。 CSS の間接セレクタなどを応用して、「ホバー状態の input type=file の兄弟である input type=submit」といったセレクタ指定の上で表示効果を与える必要があろう。 また、Tab キー押下によるフォーカス移動で、input type=submit 要素へフォーカス移動してしまうのは避けたほうがよいかもしれない。 tabIndex 属性に -1 を指定するなどして回避するのがよいだろう。 ソースコードは GitHub で以上、ソースコード一式は GitHub にて公開済み。https://github.com/jsakamoto/FileUploadSample/tree/alternate-way master ブランチが、最初に実装した、IE 相手には通じなかったオーソドックスな実装。 alternate-way ブランチが IE にも対応した input type=file 要素を重ねる実装である。 サーバー側実装には、C#+ASP.NET Web Pages(Razor Syntax) を使っている。 しかし今回のテーマはサーバー側技術はとくに関係はしない。 よって、別にサーバー側部分は読み解けなくとも支障はないだろう。 どうぞご参考まで。 まとめ以上、input type=file 要素を表示上は見せないで、プラグインは使わない標準の HTML + CSS + JavaScript によるアップロードフォームの作り方を紹介した。この技法そのものは、StackOverflow.com をはじめ、よそでも既出のもので、目新しいテーマではない。 同じことをやっている大手一般サイトもちらほらお目にかかる。 しかしながら、いいまとめが見つからなかったので、あえて自ブログにも掲載した次第。
by developer-adjust
| 2012-09-23 19:07
| Web系一般
|
Comments(0)
|
ファン申請 |
||