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

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

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

関連ページ
  1. MovableType4
  2. Ajax
  3. PHP
TRASH-NEWSは
いろいろと紙一重なニュースサイトです
初出時刻
2008年01月17日 03時52分 投稿
最終更新時刻
2008年02月21日 13時20分 改訂
  • この記事をはてブする
  • Yahoo!ブックマークに登録

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

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のギガントなログがオートセーブされ続けるところでした。

サイト内検索
検索する
このサイトについて
  • サイト名 : TRASH-NEWS
  • 分類 : ニュースとネタのサイト
  • ジャンル : 井戸端からアレゲまで
  • もっと詳しく見る
最近の記事
08月19日の記事
  1. こもんちゃん(ニコニ・コモンズ)で解説する『PhotoshopCS3でアニメgifを編集する方法』
08月18日の記事
  1. ブルースクリーン・ブルース
08月17日の記事
  1. 夏コミのために有給を取ったにもかかわらず
07月16日の記事
  1. マルタと釘宮のために買ったWii、Priceless.
07月12日の記事
  1. 2008年7月に発売されるマンガのスケジュール表
07月06日の記事
  1. I'veコンピアルバム 『master groove circle』など気になったニュース
07月05日の記事
  1. テイルズオブ釘宮やSound Blaster Play!など購入検討物リスト
07月02日の記事
  1. うみねこのなく頃に体験版はマンガ版を読んでからのプレイがオススメ
06月22日の記事
  1. ぬらりひょんの孫のつららは細かすぎて伝わらない萌え
06月21日の記事
  1. プログラム経由で画像を表示させる際の表示バラつきを調べてみた
日刊人気記事ランキング
2008年08月20日のぶん
1
Windows XP SP3インストールで不具合が起きることが発覚
94
2
Windows XPのSP3は思いのほかスゴいらしい
38
3
テイルズオブ新作『テイルズ オブ ヴェスペリア』のまとめと推察
37
4
XP SP3における不具合報告と32bitOSでのメモリのRAMDisk化の話
32
5
テイルズオブヴェスペリアはXbox360で発売決定?
28
6
ぬらりひょんの孫のつららは細かすぎて伝わらない萌え
22
7
デトロイト・メタル・シティ(DMC)アニメ映画&実写映画化決定
19
8
画像解析系ジェネレータ・BannerCodeBattler2(仮)着手開始
19
9
PSP版スターオーシャン2の既報のまとめと新旧声優対応表
18
10
うみねこのなく頃に体験版はマンガ版を読んでからのプレイがオススメ
17

2008年08月21日 0時更新

人気記事ランキング

カテゴリ(折畳表示)
ニュース・ネタ
サブカテゴリを開く
俺研究舎
サブカテゴリを開く
お知らせ
サブカテゴリを開く
特集・企画
サブカテゴリを開く
管理人近況
サブカテゴリを開く
カスタムアーキテクチャ
1回めのようこそ!
ゲストさん
  • 文字の大きさ : 12px
  • フォント : MS Pゴシック
  • レイアウト : 3段組
  • カスタムする
カレンダー
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    
管理人について
管理人 : 八満かシアン
文系なのにエンジニア、なんてこったい(八満のほう)
今頃たぶん聴いている曲
乙女学入門 by Rita
月別アーカイブ
2008年
2007年
最近記事に掲載した画像
ラタトスクとWiiはマルタと釘宮のために存在している
ラタトスクとWiiはマルタと釘宮のために存在している
夏海ケイ作画『うみねこのなく頃にEP1』が面白い
夏海ケイ作画『うみねこのなく頃にEP1』が面白い
Opera9.5でニコニコ動画のキャッシュを管理しやすくするスクリプト
Opera9.5でニコニコ動画のキャッシュを管理しやすくするスクリプト
Opera9.5正式版のちょっと困ったポイント
Opera9.5正式版のちょっと困ったポイント
マジカノ最終巻、カプレカ1巻など
マジカノ最終巻、カプレカ1巻など
画像に関するリンク
ユーティリティ
RSSフィード
ソーシャルブックマーク
  • iGoogle
  • はてなアンテナにTRASH-NEWSを追加する TRASH-NEWSのはてなブックマーク数 この記事を含むはてなブックマーク
サイトプロフィール
Powered by
  • Movable Type 4.1 + [XHTML + CSS + JavaScript] + PHP
  • TRASH-NEWS / Hachiman_Cian 2007-
このページについて
題名
書きかけの記事でも何でも自動保存してくれるJavaScript+PHP
内容
  • 作成を思い立った悲劇はひとつまえの記事を参照してください。 MovableTyp
TRASH-NEWS ロゴ
TRASH-NEWS ロゴ
TRASH-NEWS : http://www.trash-news.net/