TRASH-NEWS 2008年01月17日の記事一覧

順路
  1. ホーム
  2. 2008年
  3. 01月
  4. 17日 [現在地]
Search?
お知らせ
ここ数日更新が滞っていますが…… (2008/04/13 13:31)
4月より社会人となったため、時間の作り方がいまいちつかめないため、不定期の更新となります。まぁ……ニコニコメーカーでもお楽しみください!
1 2 3

2008年01月17日

2008年01月17日のニュースとネタをお届けします

関連した日付へのリンク
  1. 2008年の記事一覧
  2. 2008年01月の記事一覧
TRASH-NEWSは
いろいろと紙一重なニュースサイトです

2008年01月17日本日のニュースとネタ

作成を思い立った悲劇はひとつまえの記事を参照してください。

MovableTypeへの恨みは技術の壁を乗り越えました。タイトルの通り、書きかけの記事(でも何でも)を自動保存してくれるAjax(JavaScript+PHP)なプログラムを突貫で作りました。もともと俺clap!で導入するはずだった機能を必要な部分だけ切り取って持ってきたのでMovableType4だろうがMovableType3だろうが理論上はmixiの日記だろうが果てはあなたのパソコンのメモ帳だろうが、なんでも書きかけの記事を自動保存してくれます。

流れとしてはJavaScriptで記事作成画面のテキストエリアの内容を読み込み、それをサーバー上のPHPのプログラムに送信してファイルに保存する、といった感じです。つまりJavaScriptはテキスト内容を送るだけ、PHPは送られてきた内容を保存するだけ、という役割分担です。逆を言えば両方揃って使えないと意味がありません。

以下JavaScriptとPHPのソースを書きます。なおJavaScriptはXMLHttpRequestという、最近Ajaxなどで利用されている関数を用いています。旧いブラウザだと動かない恐れがあります。また確か違うドメインへのアクセスはできないはずなので、JavaScriptと同じドメイン下でPHPが動かせないとダメです(普通は大丈夫)。こちらではOpera9とIE7、FireFox2でJavaScriptの動作確認を、PHP5.23でPHPの動作確認をそれぞれ行いました(PHP4でも問題なく動くはず)。

書きかけの記事でも何でも自動保存してくれるJavaScript
var SaveID; window.TimerList = new Array(); function noticeStatus(notice){ var StatusLayer = "StatusLayer"; // StatusLayerというidのブロックをページ上に作ると自動保存の成否を報告してくれる(Ajax?) if(statusBar = document.getElementById(StatusLayer)){ statusBar.innerHTML = notice; } } function setAutoSaver(SaveID,SaveBody){ if(!window.TimerList[SaveID] || !isNaN(window.TimerList[SaveID])){ exeSeconds = 60; // 指定秒ごとにformSaverを呼び出す noticeStatus('Save : ' + SaveID + ' (every ' + exeSeconds + ' seconds)'); window.TimerList[SaveID] = setInterval(function(){formSaver(SaveID,SaveBody);},1000 * exeSeconds); return; } } //データを保存するプログラム(PHP)を呼び出す function formSaver(SaveID,SaveBody){ var httpObj; var dt = new Date(); var dtH = dt.getHours(); var dtM = dt.getMinutes(); var dtS = dt.getSeconds(); var AutoSaverProgram = "http://~.php(ここに後述のPHPプログラムのURL)"; if(httpObj = createXMLHttpRequest()){ noticeStatus('ID:' + SaveID + ' - Now Saving...'); }else{ noticeStatus('ID:' + SaveID + ' - Fail?'); } if(SaveBody.value == ""){ noticeStatus('ID:' + SaveID + ' is not auto-saved( = NULL)'); return; } httpObj.open("post",AutoSaverProgram,false); httpObj.setRequestHeader("content-type","application/x-www-form-urlencoded;charset=UTF-8"); httpObj.onReadyStateChange = function() { //サーバ側の処理終了 if(httpObj.readyState == 4){ if(httpObj.Status == 200) { noticeStatus('ID:' + SaveID + ' - Success Auto-Saving!!'); }else{ noticeStatus('Connect Error'); } }else{ noticeStatus('ID:' + SaveID + ' - Fail Auto-Saving!!'); } } //フォームの入力データを送信 httpObj.send("Body=" + encodeURIComponent(SaveBody.value) + "&ID=" + encodeURIComponent(SaveID)); noticeStatus('ID:' + SaveID + ' - Auto-Saved(' + dtH + ':' + dtM + ')'); return true; } function createXMLHttpRequest(){ if(window.XMLHttpRequest){ httpObj = new XMLHttpRequest(); }else if(window.ActiveXObject){ try{ httpObj = new ActiveXObject("Msxml2.XMLHTTP"); }catch(e){ httpObj = new ActiveXObject("Microsoft.XMLHTTP"); } } return httpObj; }

以上を"DraftAutoSaver.js"とでも名前をつけて保存、アップロードしてください。オートセーヴァーって書くとかっこよいですね(どうでもいい)。

なおXMLHttpRequestまわりの処理についてはOpenSpaceさんのAjaxを勉強しようコーナーのこの記事を参考に作りました。よって正しい書き方かどうかわかりません。ま、動いているから大丈夫ですよ(無責任)!

さてそれではもう一対のPHPプログラムのほうを。JavaScriptの働きを“オート”と表現するならこちらは“セーブ”です。

書きかけの記事でも何でも自動保存してくれるPHP
if(isset($_POST['ID']) && isset($_POST['Body'])){ $ID = $_POST['ID']; $Body = $_POST['Body']; $FileName = "ログファイルを置くサーバー上のフォルダ" . "DraftAutoSaved_". $ID . ".cgi"; if(file_exists($FileName)){ $PutData = file_get_contents($FileName); $PutData = unserialize($PutData); $LogCount = count($PutData); $LogFileSize = filesize($FileName); if($LogCount >= 30 || ($LogFileSize >= 150000 && $LogCount >= 10)){ array_shift($PutData); } $LastPutData = end($PutData); }else{ $LogCount = 0; $PutData = array(); $LastPutData = ""; } $LogCount++; $NowDate = $LogCount . " " . date("Y/m/d G:i:s",time()); if($Body != $LastPutData){ $PutData[$NowDate] = $Body; $PutData = serialize($PutData); file_put_contents($FileName,$PutData,LOCK_EX); } header("HTTP/1.0 200 OK"); exit(); }

ログファイルを置くサーバー上のフォルダ、という部分だけ書き換えてください(ex. /public_html/php/log/)。ここにログが保存されます(パーミッションは666くらいに設定)。あとは普通のPHPファイルとして保存してサーバー上に設置するだけです。パーミッションは755くらい? 先述のJavaScriptのformSaverという関数にある“後述のPHPプログラムのURL”のところと、このPHPプログラムの名前をあわせることも忘れずに。

このPHPプログラムは『PHP的な意味でシリアライズして配列のデータとして保存する』、『30コ以上配列(=ログ)は保存しない(古い順から消していく)』、『最後に書き込んだ内容と同じ内容が送信されてきた場合は上書き保存しない(何もせずにフェーズ終了)』仕様となっています。my_file_put_contentsなんて使いませんよ(PHP4の方は左記の記事を参照してください)。

あとは自動保存したいページのヘッダでJavaScriptを呼び出し、そして自動保存したいtextareaタグに以下のように記述するだけ。

onclick="setAutoSaver('Body',this);"

これで指定したフォルダに毎指定秒、『DraftAutoSaved_Body.cgi』という名前で自動保存されていきます。setAutoSaver関数の第1引数である"Body"の部分を書き換えると保存するログの名前も変わるので、いくつでもこの自動保存機能をつけることができます。また保存するファイルの拡張子がcgiとなっているのは外部からのアクセスを遮断するためです。

セキュリティ面で言えばこのPHPプログラムと生成されるログファイルは隠蔽+保護しておくべきです。しかしプログラムのURLはJavaScriptのなかに書き込まなければならない都合上隠蔽できません。よって必ずhtaccessなどで悪意のある第三者がアクセスできないよう対策を施してください。保存開始のたびに認証が求められますがそれ以降は認証が出てきませんし、逆に自分の気づかないところで自動保存が始まっていて負荷が高まっていたなんていうこともなくなるので安心です。ログを出力するフォルダもそもそもhtaccessで保護しておけば完璧でしょう。

さて今回のこの一連のプログラムをMovableType4に適用するための方法を以下にご紹介します。

エントリー編集画面は『mt/tmpl/cms/edit_entry.tmpl』というテンプレートによって作成されています(MovableType4.01基準)。このedit_entry.tmplを下記の2ヶ所カスタマイズします。

edit_entry.tmplの207行目(に挿入)
旧 : (挿入)
新 : <script type="text/javascript" src="/DraftAutoSaver.js"></script>
↑ヘッダの部分にJavaScriptを呼び出す一文を加えるわけです

edit_entry.tmplの867行目(を書き換え)
旧 : <textarea id="editor-content-textarea" ~ >
新 : <textarea onclick="setAutoSaver('Body',this);" id="editor-content-textarea" ~ >
onclickで関数を呼び出すわけです(このあたりは関数を呼び出せればなんでも良)

これで稼動できる状態になりました。必要なファイルを設置したら記事を作成する画面にアクセスしてみてください。見た目は何も変わっていませんが、きちんと“自動保存してくれる”textareaに変わっているはずです。ソースを表示して確認しておくと良いかと思います。なおこの部分は残念なことにMobvableTypeをバージョンアップさせるたびに自分で書き直す必要がありますのでお忘れずに(かくいう自分も)。

さて先述のとおりこの2つのファイルを組み合わせればどんなフォームの文章でも下書きを保存することができます。ApacheとPHPをパソコンにインストールしてローカルでもPHPを動かせるようにすれば、普段使っているパソコンで同等の機能が実現します。これでメモ帳も強まりますね。

実際たいしたことのないプログラムですが、あると嬉しい+組み合わせれば無限の可能性が広がる、ということで取り急ぎご紹介しました。これで僕も無用な心配から解放されます。

[超ご注意] 思いつきで作ったものなので処理に穴がある危険性があります。利用は自己責任でお願いいたします。またこのページ(と各関数)は更新する場合がありますので、定期的に確認することをオススメします。またこのプログラムがAjaxと呼んでいいかどうかわかりませんのでそのあたりはお互いこっそり“Ajaxだぜウヒヒ”とか思い込んでおきましょう。

[そういえば] 保存することだけに夢中になっていたため閲覧するプログラムを作り忘れていました。まぁ、気が向いたら作ります。

[超ご注意II] 現に一部を書き換えましたのでお知らせいたします(1/17 AM5:00)。formSaverの関数内でencodeURIという関数を使っていましたが、encodeURIComponentでないと一部の文字列で不具合があることがわかりました。具体的には"+"などの文字があるとうまくJavaScriptでpost送信できないようです。理論上は確かにその通り……PHPばかりやっているとそのあたりのことを忘れがちになるから困る。

[超ご注意III] とても危険な誤りがありました(1/18 PM4:00)。
× : if($LogCount >= 30 && ($LogFileSize >= 150000000 && $LogCount >= 10)){
○ : if($LogCount >= 30 || ($LogFileSize >= 150000 && $LogCount >= 10)){
150MBのギガントなログがオートセーブされ続けるところでした。

[ 関連キーワード : (キーワードは登録されていません) ]

いますごいいい調子で『MacBook Air』についてのエントリーを書いていたんですよ。でもね、またなんですよ。またMovableTypeにやられました。投稿ボタンを押したらサインインが求められ、サインインしようとしても『ログインできませんでした』。Operaの強力な『戻る』機能を利用しても、iframeの中の入力内容までは復帰できないため一生懸命書いた記事データは全部水の泡。ムリだろうなとあきらめつつも試みたMovableType4標準の記事自動保存機能も、当然ログイン情報が切れる時点での記事データ、つまりは中途半端な状態でのデータしかセーブされていないのでまるで意味がなく。

MovableType4については何度も書くようにJavaScriptの挙動がおかしかったりログイン状態がスパスパ切れたりhtml上の設計が狂っていたりするので非常に頭にきます。JavaScriptがおかしいのはOperaを使っているせいかもしれないので保留。ログイン情報がきれやすいのはどうもデータベース(MySQL)との通信エラーによるものらしいので保留。ただiframeばかり使う設計にだけは耐えられません。iframeはとっくの昔に廃棄されるはずだったhtml規格上のお荷物であり、使用は非推奨されている存在。そんなものを使い続けている理由がどこにあるのかはわかりませんが、モダンブラウザを使っているぶんには明らかに悲劇しか生まない仕様であるはずなので本当にやめてもらいたいですね(だからといって代替推奨のobjectタグであろうと同罪)。webアプリケーションで外部のデータを安易に引っ張ってくるなと。

今回はいよいよ度重なる不満が爆発しました。僕がいかにMacBook Airについて必至に書こうとしていたか……わざわざMacヘビーユーザーの先輩にいろいろアドバイスしてもらったりしたのに! そして1時間以上かけて書き綴った執念とその成果を全否定されたら! どんな気持ちになるかMovableType4のJavaScriptに全否定されたこの思いは、3倍にして返すしかありません。

自作で“MovableTypeの仕様に縛られない自動保存機能”をもったJavaScriptを作ります。毒には猛毒をもって制す。2時間くらいお待ちください。

[追記] 完成しました。

書きかけの記事でも何でも自動保存してくれるJavaScript+PHP

勢いあまっていつの間にかAjaxっぽく作ってしまいました。

[ 関連キーワード : (キーワードは登録されていません) ]

サイト内検索
検索する
このサイトについて
  • サイト名 : TRASH-NEWS
  • 分類 : ニュースとネタのサイト
  • ジャンル : 井戸端からアレゲまで
  • もっと詳しく見る
この日の人気記事ランキング
日刊人気記事ランキング
2008年01月17日のぶん
記事タイトル

2008年01月18日 0時更新

人気記事ランキング
1テイルズオブ新作『テイルズ オブ ヴェスペリア』のまとめと推察86
2テイルズオブヴェスペリアはXbox360で発売決定?69
3PSP版スターオーシャン1のプレイ雑感と感想46
4DS版DQ5に“新たなる人生の選択”が追加されるよう40
5“「呪いの館」をスタイリッシュにしてみた”「呪いの館EX」をプレイしてみた40
6DS版FFIVにゲーム進行が不可能になる不具合38
7ハヤテ新EDテーマ「木の芽風」を歌うIKUはAKIなのか(I've SOUND)33
8書きかけの記事でも何でも自動保存してくれるJavaScript+PHP32
9MovableType4の自動保存機能JavaScriptを全力で否定する記事31
10マリオっぽい自作のゲーム改めしょぼんのアクション公開開始30
カテゴリ(折畳表示)
ニュース・ネタ
サブカテゴリを開く
俺研究舎
サブカテゴリを開く
お知らせ
サブカテゴリを開く
特集・企画
サブカテゴリを開く
管理人近況
サブカテゴリを開く
カレンダー
2008年1月
«  12月 - 02月  »
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    
管理人について
管理人 : 八満かシアン
理系になり損ねた文系人間(シアンのほう)
今頃たぶん聴いている曲
Cream+Mint by KOTOKO
月別アーカイブ
2008年
2007年
ユーティリティ
RSSフィード
ソーシャルブックマーク
  • iGoogle
  • はてなアンテナにTRASH-NEWSを追加する TRASH-NEWSのはてなブックマーク数 TRASH-NEWSを含むはてなブックマーク
サイトプロフィール
Powered by
  • Movable Type 4.1 + [XHTML + CSS + JavaScript] + PHP
  • TRASH-NEWS / Hachiman_Cian 2007-
このページについて
題名
2008年01月17日の記事一覧
内容
  • 2008年01月17日のニュースとネタをお届けします
TRASH-NEWS ロゴ
TRASH-NEWS ロゴ
TRASH-NEWS : http://www.trash-news.net/