公開日:2013.06.12

プレビュー画面を作ったよ

テクログ

今、fuelphpというフレームワークを使ってブログ機能みたいなのを作っているのですが、独自で作っているからもう何がなにやら分かりません。

で、ブログをアップする前にプレビュー画面の表示をさせたいということで、Jqueryを使ってデータの受け渡しに挑戦!

参考にさせていただいたのはコチラ!

ありがとうございます。

テキストや既存の画像は上のJqueryプラグインをちょちょいと修正すれば、さくっと表示できる。

実際作ったpreview.jsはこんな感じ。


(function($){
?$.fn.previewButton = function(config){
??var button = this;
??var defaults = {
???//プレビューのurl
???"url" : null,
???//キーとタイプのハッシュ {key:type, …}
???"post" : {}
??};
??var config = $.extend(defaults, config);

??if (config.url){
???button.live("click", function(){
????var form = $(this).parents("form");
????var newform = $("
");
????$("body").append(newform);
????$.each(config.post, function(i, val){
?????switch(val){
??????case "title":
???????var _val02 = $("#edit_news_title").val();
???????newform.append( form.find("input[name = " + i + "]").clone().val(_val02));
??????break;
??????case "textarea":
???????var _val = $("iframe:first").contents().find(".cke_editable").html();
???????newform.append( form.find("textarea[name = " + i + "]").clone().val(_val));
??????break;
??????case "category":
???????var _val03 = $("#edit_news_category").find(":selected").text()
???????newform.append( form.find("[name = " + i + "]").clone().val(_val03));
??????break;
??????case "new_category":
???????var _val04 = $("#edit_news_newcategory").val();
???????newform.append( form.find("input[name = " + i + "]").clone().val(_val04));
??????break;
??????case "tag":
???????var _val05 = $("#edit_news_tag").val();
???????newform.append( form.find("input[name = " + i + "]").clone().val(_val05));
??????break;
??????case "topimg_main":
???????var _val06 = $("#edit_news_topimg").val();
???????newform.append( form.find("[name = " + i + "]").clone().val(_val06));
??????break;
??????case "writer":
???????var _val07 = $("#edit_news_writer").val();
???????if(_val07 ==""){
????????_val07 = $("#edit_news_topimg").find(":selected").text();
???????}
???????newform.append( form.find("input[name = " + i + "]").clone().val(_val07));
??????break;
??????default :
??????break;
?????}
????});
????window.open(this.href, "preview");
????newform.attr("target", "preview");
????newform.attr("action", config.url);
????newform.attr("method", "post");
????newform.submit();
????newform.remove();
????return false;
???});
??}
?};
})(jQuery);

(function($){
?if(1){
? $("input#form_preview").previewButton({
???"url" : "preview",
???"post" : {
????"text" : "textarea",
????"title" : "title",
????"category" : "category",
????"new_category" : "new_category",
????"tag" : "tag",
????"topimg_main" : "topimg_main",
????"writer" : "writer",
???}
? });
?}
})(jQuery);

ちゃんと表示されてるかなぁ?

POSTを受け取るコントローラーはこんな感じ。


?public function action_preview()
?{
??$data = "";
??//POSTの値を変数に格納
??if(!empty($_POST["title"])){
???$data["title"] = $_POST["title"];
??}else{
???$data["title"] = "";
??}
??if(!empty($_POST["text"])){
???$data["text"] = $_POST["text"];
??}else{
???$data["text"] = "";
??}
??if(!empty($_POST["category"])){
???$data["category"] = $_POST["category"];
??}else{
???$data["category"] = "";
??}
??if(!empty($_POST["new_category"])){
???$data["new_category"] = $_POST["new_category"];
??}else{
???$data["new_category"] = "";
??}
??if(!empty($_POST["topimg_main"])){
???$data["topimg_main"] = $_POST["topimg_main"];
??}else{
???$data["topimg_main"] = "";
??}
??if(!empty($_POST["writer"])){
???$data["writer"] = $_POST["writer"];
??}else{
???$data["writer"] = "";
??}
??if(!empty($_POST["tag"])){
???$data["tag"] = $_POST["tag"];
??}else{
???$data["tag"] = "";
??}
??//セッション関数
??Session::set_flash("pre_title", $data["title"]);
??Session::set_flash("pre_text", stripcslashes($data["text"]));
??Session::set_flash("pre_category", $data["category"]);
??Session::set_flash("pre_new_category", $data["new_category"]);
??Session::set_flash("pre_topimg_main", $data["topimg_main"]);
??Session::set_flash("pre_writer", $data["writer"]);
??Session::set_flash("pre_tag", $data["tag"]);

??return View::forge("ビューファイルの場所が入るよ!", false);
?}

POSTで得た情報をセッションでviewに渡すだけの簡単な作りです。

で、困ったのが、?Jquery.upload.jsを使って、『画像を一時的にuploadしたものをプレビューに表示する』というもの。

そもそも、初心者の僕はいろんな処理が絡むような、また、ファイルの受け渡しが複雑になるような部分が根本的に苦手なようで、このふたつの処理をうまく理解することが出来なかった。

はじめに、上のプレビューのコードにfileを追加したら、アップロードしようとしている画像ファイル名は取得できたけれど、上記のようにプレビュー画面に反映することは勿論出来なかった。

それはアップロードが出来ていなかったからだ!(当たり前)

そこで、まずはJquery.uploadのコードを見てみる。


$(function(){
?$("#edit_news_uploadimg").change(function(){
??$(this).upload("demo.php", function(res){
???alert(res);
??},"html");
?});
});

これ、合ってそうじゃない!?合ってそうだよね!?

そして、アップロード先のurlであるdemo.phpを試しに作っておいてみる。(アップロードが出来れば僕らの勝利なのだから。)

コードは色々と端折ってますがこちら。


// ※$_FILES["file"]["tmp_name"]がテンポラリにあるファイル名
// ※$_FILES["file"]["name"]がアップロード元のファイル名

//tmpからファイルをコピー
$tmpimg_file = date("U").".jpg"; //※便宜上jpgにしているだけだよ!
move_uploaded_file($_FILES["file"]["tmp_name"],$tmpimg_file);
//セッションに格納
Session::set_flash("pre_file", $tmpimg_file);
return "一時アップロードしました";

合ってそう!合ってそうだよ!!

でも、どうしても取れない。

ちゃんとそのdemo.phpを見ているかの確認もしたし、alert(res) の部分をalert(“死んで俺に詫び続けろオルステッド”) とかにするとちゃんと出てくるのに、resが取れないし、ファイルもアップロードされない。

僕らは、一言「一時アップロードしました」って言って欲しいだけなのに……。

で、この解決の鍵は『MVC構造、及びフレームワーク』に隠されていました。

「MVC構造、及びフレームワーク」の特徴として、必ず「コントローラー」を経由して「ビュー」に受け渡しするのは当たり前ですよね。

そう、その当たり前が抜けていた。

コントローラー…….?

public function action_demo() 作ってない!!!

そうさ、上記のdemo.phpをviewファイルに作ってもコントローラー作ってなきゃ受け渡しされるはずが無いのでした。

そうなると、別にアップロード先にviewなんて要らないから、コントローラーでアップロードの処理をしてしまえば良い。

おまけにここで画像ファイルかどうかの判定も入れてしまおうかと。

editer機能のコントローラーに以下を追加。


?public function action_demo()
?{
??// ※$_FILES["file"]["tmp_name"]がテンポラリにあるファイル名
??// ※$_FILES["file"]["name"]がアップロード元のファイル名

??//拡張子取り出し
??$preview_extension = explode(".", $_FILES["file"]["name"]);
??//画像ファイル拡張子タイプを配列に
??$extension_type = Config::get("app.img_extension");

??//画像ファイルかどうか判定
??if(array_search($preview_extension[1],$extension_type) === false){
???return "画像ファイルを選択してください";
??}
??//tmpからファイルをコピー
??$tmpimg_file = "????????????????".date("U").".".$preview_extension[1];
??move_uploaded_file($_FILES["file"]["tmp_name"],$tmpimg_file);
??//セッションに格納
??Session::set_flash("pre_file", $tmpimg_file);
??return "一時アップロードしました";
?}

これで画像ファイル判別+リネーム+tmpファイルへのアップロードが完了。

上記コードの「Session::set_flash(“pre_file”, $tmpimg_file)」でセッションにSET。
※これはfuelphpの便利なメソッドだよ!

プレビュー画面のviewで、 「Session::get_flash(“pre_file”)」でファイル情報をGETして表示完了!

※セッションで表示させるのとか合ってるのかなぁ、正直謎だ……..

ハハッ!ここで勘の良いお方はお気付きのはずだ!

これ、jquery.uploadでアップロードした画像のみ、一番上のコードのpreviewのJquery使ってないんです…..

preview.js も public function action_preview() も、どっちも全くコード弄っていない。

ここわかんねー!!!

Js間で絡むと思ってましたよ。。いや、絡ませる方法もあるんだろうな。

いやはや、これでなんとかプレビュー画面完成です。

最後に、tmpファイルに溜まっていく画像データをcronで一定時間したら消す処理を忘れないように!パンパンになるよ!!

終わり

この記事を書いた人

core-corp

入社年2010年

出身地東京都

業務内容インフラ

特技または趣味ドライブ

core-corpの記事一覧へ

テクログに関する記事一覧