Ajaxっぽいファイルアップロード

もう2年も前のエントリだけど、id:yamazさんの記事が役に立ちました。ありがとうございます。

Ajaxっぽく画面遷移なしでファイルアップロードしたい!」

と思っていたところ,こんなページが見つかった.

http://sean.treadway.info/demo/upload/

であれこれ解析していたところ,のりおさん@RailsChatからナイスなモノを教えてもらった(同じサイトなのに気づかなかった).

http://sean.treadway.info/svn/plugins/responds_to_parent/

結果として画面遷移なしでファイルのアップロードができるようになった.

大変勉強になったんだけど、responds_to_parentは使わなくていいんじゃないかなと思いました。


まず最初のHTML。これはRailsのビューでもいいし、静的なHTMLでもOK。
ポイントは iframeを入れとくことと、formのtargetをそのiframeを指すように設定すること。これでformをsubmitするとiframeにサーバーのレスポンスが出力されます。あ、enctypeも指定しないとね。

<div id="stuff">Here is some stuff</div>
<form target="frame" action="form_action" enctype="multipart/form-data" method="post">
  <input type="file" name="uploaded_file"/>
  <input type="submit"/>
</form>
<iframe id='frame' name="frame"></iframe> <!-- ← Upload用ダミーIframe -->

で、stuffの中身を更新したい場合の出力は素のJavaScriptを使ってこんな風に書けます。

<div id="partial_content">
div#stuffに出力したい部分。partialとかで書くと楽かも。
</div>
<script>
var content = document.getElementById("partial_content");
var dest = window.parent.document.getElementById("stuff");
dest.innerHTML = content.innerHTML;
</script>

これで出力されたHTMLを、staffにコピーして表示できます。実際は名前空間を汚染しないように (function(){ ... })(); で囲ってください。

要はiframeに出力されたHTMLで、特定の要素の中身をiframeの外側の要素に window.parent...でアクセスして、適切な要素のinnerHTMLを書き換えているだけです。らくちんっすね。