jQuery UI の sortable でらくらく並び替え
データを登録するシステムを作ると、必ずといって良いほど出てくる要望の一つが「編集」と「並び替え」。
この2番目のデータを1番に持って行きたいんだけれど…。
なんて事をよく言われますが、マウスでヒュンヒュンと入れ替えする為には便利な jQuery の ユーザーインターフェースライブラリを使うと簡単にできちゃいます!
1. jQuery UI のサイトから、ライブラリをダウンロードします!(→ 公式)
2. ダウンロードして展開したら「css」フォルダをまるごと使いますので組み込むシステムにコピーします。
画像では「ui-lightness」というフォルダ名になっていますが、jQuery UI よりダウンロードする際にテーマを選択する事によってフォルダの名称が異なりますのでご注意ください。
3. システムに読み込む
<link type="text/css" href="css/ui-lightness/jquery-ui-1.7.2.custom.css" rel="stylesheet" />
4. ヒュンヒュンする為の javascript もあわせて読み込みましょう!
<script type="text/javascript" src="js/jquery-1.3.2.min.js"></script> <script type="text/javascript" src="js/jquery-ui-1.7.2.custom.min.js"></script>
これで準備は整いました。
次にヒュンヒュンターゲットをプログラムで出力します。 jQuery UI の sortable は例えば table の中の tr 単位でも並び替えができますし、さらには tr の中の td単位でも並び替えをする事ができます。
ここでは、ulにて整形されたリストの並び替えを行います。
<ul id="hyunhyun"> <li id="tobi">とびだせヒュン<li> <li id="sore">それゆけヒュン</li> <li id="ikko">どんだけヒュン</li> </ul>
それでは、このリストを並び替えますので HTML のヘッダー部に sortable を追加します。
$("#hyunhyun").sortable({
update: function(event, ui) {
$("#hyun_sort").val($('#hyunhyun').sortable('toArray').toString());
}
})
.disableSelection();
1行目は、id が hyunhyun と指定された ul に sortable を設定しています。そして、2行目より sortable のプロパティを設定し、update はドラッグ&ドロップが終わった際に実行されるイベントです。
この例では、id を hyun_sort と指定した hiddn のタイプを指定した inputタグの value値に並び順をセットしています。実際にセットされる値は、並び順により liタグの id値がカンマ区切りになります。例のリストの場合には、
tobi,sore,ikko
という情報が入りますので、submit 後は php プログラムにて カンマ(,)で explode すれば、順番通りに id が取得できます。 データの並び順を記録するフィールドなどをアップデートすれば、ヒュンヒュンと並び替えが行えます!
やったね!
おまけ。
sortable には色々なプロパティが用意されており、それを設定すると見栄えがよくなったり、操作性が向上するよ!例えば、
placeholder … css のクラス名を指定します。例えば、 background を指定すると並び替え時に、並び替え先となる場所が予め色が変わるので、どこにリストが移るのかが判りやすくなります!
handle … 例では li 要素の全体がドラッグ&ドロップ対象になってしまいますが、li要素上の一部分だけをドラッグ&ドロップ対象にする事ができます。ドラッグ&ドロップ時の「持ち手(取っ手)」というイメージでしょうか。
axis … ドラッグ&ドロップ時に、自由自在に要素を動かすことができますが X軸またはY軸の方法にのみに限定したい場合は、 x または y を指定しましょう。
cursor … ドラッグ&ドロップ時のマウスカーソルの形状を css の cursor と同等に設定することができます。やっぱり move (十字の矢印)にしたいですよね!
他にも色々あるので、詳細は公式ドキュメントを是非!
自ページにリンクしているアンカーの親要素の css を書き換える
顔の黄色い人(@yashio)がなんか困っているようなので。
すごく解りづらいタイトルですが、 web app theme を使っていると ページヘッダー部の main-navigation 内の li 要素に対して active という class を指定すると、スタイルが変更される、という仕組みになっています。
上図「Active」という部分が該当します。
1ページずつ編集する事を考えると、ヘッダーやフッターをテンプレート化した際にとても面倒なので、私は以下のような javascript を使って対応しています。
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">google.load("jquery", "1.3.2");</script>
<script type="text/javascript">
$(document).ready(function() {
var uri = location.href;
if (uri.match(/(https?[^?]+)(#.*)/)) {
uri = RegExp.$1;
}
$("#main-navigation li").find("a[href='"+uri+"']").parent().addClass("active");
});
仕組みは、現在表示しているURLを取得して、そのURLをリンクしているa要素を探しだして parent() により親要素のclassに active を設定する。
という単純なものです。
このプログラムのままでは、リンクを完全なURL形式で書かないとリンクになりませんので注意が必要です。
メール受信で codeigniter の メソッドを起動する方法
空メールを受信して会員登録用のURLを返信したり、ケータイから画像添付メールを受信して掲示板に投稿させたりと、何かと出番の多い「メールから php プログラムを起動する」 という処理ですが Codeigniter での情報がありませんでしたのでまとめてみます。
元々、Codeigniter の 特定のコントローラーのメソッドを cron で呼び出す為のプログラム(Cron job bootstrapper)は公開されていますので、そんなに難しくはないだろうと思っていたんですが、見事にハマってしまいました…。
なんで Cron として動作させるプログラムが関係あるのか。
ものすごーく単純に考えると Cron として動作させる為には shell(コマンド)として codeigniter の特定のコントローラーのメソッドを呼び出して動作させる仕組みが必要になります。 Cron は、指定した時刻に指定したコマンドを実行するものですが、メール受信でプログラムを呼び出すのも、同じ様にメールを受信したタイミングで指定したコマンドを実行する事から、
たぶん、crontab に書くのと同じ要領で動く。
と考えたのでした。
Cron job bootstrapper のインストール
まずは、Cronjob bootstrapper の wiki ページに掲載されているコードをコピーして適当なファイルに保存します。ここでは、 cron.php として UTF-8/LF にて保存しました。
保存したファイルを動作させる環境にあわせて書き換えをします。
書き換えるのは、
define('CRON_CI_INDEX', '/var/www/vhosts/intranet/index.php'); // Your CodeIgniter main index.php file
このパス指定です。
実際には、その他に@mataga さんのブログ「ヌル日記」の記事「[CodeIgniter][PHP]CodeIgniterの学習 52 – CodeIgniterをバッチとして呼び出せるようにする」を参考にさせて頂き ob_end_flush 部についても変更を行いました。
さらに…
今回設置したサーバーが「さくらインターネット」でしたので、codeigniter を さくらインターネットで動作させている方は変更されているであろう、uri_protocol (QUERY_STRING に設定していませんか?)に合せた編集が必要になります。
wiki に上っているコードは以下のようになっており、ハイライトされている66行目は存在しません。
case '--run': // Simulate an HTTP request $_SERVER['PATH_INFO'] = $value; $_SERVER['REQUEST_URI'] = $value; $_SERVER['QUERY_STRING'] = $value; $required['--run'] = TRUE; break;
従って、–run オプションを指定し起動しても $_SERVER['QUERY_STRING'] に値が無い為、コントローラーが呼びだせずエラーが記録されてしまいます。
必ず、$_SERVER['QUERY_STRING'] = $value; を追加しておきます。
編集が終ったら、このファイルを適当なパス(私は、/home/ユーザー名/ にそのまま設置しました。)に設置し実行権限を付けておきます。
あとは MTA(sendmail とか qmail とか postfix とか!)より、メールを受信した際にプログラムを起動するように設定ファイルを作ります。さくらインターネットの場合は、「/home/アカウント名/MailBox/メールアカウント名」に .mailfilter というファイルを設置する事で受信されたメールからプログラムを起動させる事ができます。
to "| /usr/local/bin/php -q /home/アカウント名/cron.php --run=/mail/pict"
上述の例では、コントローラー: mail の、メソッド: pict が呼びだされて処理されます。 なお、先程のヌル日記の記事にもあるように、このメソッドがブラウザから呼びだされて実行されないように、ちょっとした細工が必要になります。詳細については、ヌル日記の該当記事の追記をご覧ください。
あとは、メソッド中での処理は通常の php と、通常の codeigniter の処理と同じ様に書く事ができます。
作ってみたよー!! ランダムバナーを表示する jQuery プラグイン
「ランダムにバナーを表示したい」という要望があり、データベースとか使うような大袈裟なものじゃないもの…と jQuery でなんとか実現できないものかと、ちょっと自分で作ってみる事にしました。
ソースコードは以下。
(function($){
$.fn.rb_collection = {};
$.fn.rb_collection = function(cfg) {
var that = this;
if($.browser.msie && !$.fn.random_banner.winloaded)
$(window).load(function(){ ini(cfg) });
else
ini(cfg);
function ini(cfg) {
$.post( cfg, function(data, status) {
var $items = $(".rb_collection", data);
var arr = $.makeArray($items);
var nums = Math.floor(Math.random() * arr.length);
$(that).html(arr[nums]);
}, "html");
};
};
})(jQuery);
使い方は、jQuery(1.3.2 で動作してました!) と一緒に読み込み…。
以下のように、HTML を書きます。
該当するのは、
$("#bp_holder").rb_collection('javascript/semi-item.htm');
こちらの一行。
id が bp_holder というブロック(div)に javascript/semi-item.htm の中に記述されている複数のバナーから1つを表示する。という意味になります。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="javascript/jquery.js"></script>
<script type="text/javascript" src="javascript/rb_collection.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("#bp_holder").rb_collection('javascript/semi-item.htm');
});
</script>
</head>
<body>
<!-- ランダムバナーが表示される場所 -->
<div id="bp_holder"></div>
</body>
</html>
そして、semi-item.htm には複数のバナーを並べておきます。
ファイルの拡張子からもわかるように、ただの HTML ファイルになっており…
<html> <body> <div> <!-- ひとつ目のバナー --> <table cellspacing="0" cellpadding="0" width="184" border="0" class="rb_collection"> <tr> <td>BLOG:</td> <td><a href="http://hampom.wordpress.com/"></a></td> </tr> <tr> <td>TWITTER:</td> <td><a href="http://twitter.com/hampom/"></a></td> </tr> </table> <!-- ふたつ目のバナー --> <div class="rb_collection"> <a href="http://twitter.com/hampom/"><img src="http://a3.twimg.com/profile_images/483611929/avatar.png"></a> </div> </div> <body> </html>
おおきな div要素の中に、さらに table や div といったブロックがあり css の class 指定「rb_collection」がされています。
この rb_collection が設定されている要素がランダムで元のページに出力されて表示されます。
初めて作ってみたんですが、とりあえず希望通り動いていますのでヨシとしております。改善点や問題点などがあればご指摘いただけると嬉しいです(*´д`*)
Codeigniter – Form_validationクラス
Codeigniter の Form_validation クラスのヘルパー関数。
フォームの入力内容にエラーがあった場合なんかに、再度フォームを表示する必要がある。その際に、入力された内容をフォームに予めセットしておく事をよくする。 input の type に合わせて、色々なヘルパーがある。
codeigniter フォーム・バリデーションクラス: ヘルパー関数リファレンス
set_value() なんかは、そのまま表示するものなので良いのだけれど、プルダウン(set_select)やラジオボックス(set_radio)なんかでは、 引数が3つ。
第一が select や radio フォームの名前、第二が 値、そして第三が チェックを付ける(か、選択状態にする)などの true / false になっている。
こいつが厄介で、毎度プログラムでどの値が選択されているかどうかをチェックし、 true または false をセットしなくてはいけなくて面倒だった。
そこで、 true もしくはfalse 以外の値の場合は、第二引数と比較して同一であればチェックを付けるように修正した。
/**
* Set Select
*
* Enables pull-down lists to be set to the value the user
* selected in the event of an error
*
* @access public
* @param string
* @param string
* @return string
*/
function set_select($field = '', $value = '', $default = FALSE)
{
if ( ! isset($this->_field_data[$field]) OR ! isset($this->_field_data[$field]['postdata']))
{
if (!is_bool($default))
{
if($default == $value)
return ' selected="selected"';
else
$default = false;
}
if ($default === TRUE AND count($this->_field_data) === 0)
{
return ' selected="selected"';
}
return '';
}
$field = $this->_field_data[$field]['postdata'];
if (is_array($field))
{
if ( ! in_array($value, $field))
{
return '';
}
}
else
{
if (($field == '' OR $value == '') OR ($field != $value))
{
return '';
}
}
return ' selected="selected"';
}
これと、こっち。
/**
* Set Radio
*
* Enables radio buttons to be set to the value the user
* selected in the event of an error
*
* @access public
* @param string
* @param string
* @return string
*/
function set_radio($field = '', $value = '', $default = FALSE)
{
if ( ! isset($this->_field_data[$field]) OR ! isset($this->_field_data[$field]['postdata']))
{
if (!is_bool($default))
{
if($default == $value)
return ' checked="checked"';
else
$default = false;
}
if ($default === TRUE AND count($this->_field_data) === 0)
{
return ' checked="checked"';
}
return '';
}
$field = $this->_field_data[$field]['postdata'];
if (is_array($field))
{
if ( ! in_array($value, $field))
{
return '';
}
}
else
{
if (($field == '' OR $value == '') OR ($field != $value))
{
return '';
}
}
return ' checked="checked"';
}
それぞれを、MY_Form_validation.php に追加して application の libraries に置いておけばOK.
管理画面で使うフォーム用スタイルシート MEMO
外っ面のデザインというのは本職の人がやってくれる事が多いんですが、内っ面は
「ああ、もう解ればいいんで適当にやっといてください」
と言われて毎度毎度作るのもバカらしいので、もうこれ一本にしました。既に2件ほど全く同じ管理画面ですが、さらに増える予定です(´・ω・`)
いちいち前回作ったものからコピペするのも面倒なのでここにメモしておくことに。
CSS そのものは色々なところを参考にしたりしてこのようなかたちに落ち着きました。元ネタあるのかなぁ、これ。というぐらい覚えてないんですけれど…。
あとは、幅を調整したり中央によせたりそんなんです。
※ 材料に Yahoo! UI Library の Base CSS は使っております。
スタイルシート
fieldset {
padding: 5px 10px;
border-style: solid;
border-width: 1px;
border-color: #eee;
}
legend {
padding: 0 10px;
}
label {
width: 120px;
float: left;
margin-right: 0.5em;
display: block
}
fieldset p span {
color: #CC0000;
font-size: 80%;
display: block;
}
fieldset p {
zoom: 100%;
}
fieldset p:after {
content: ".";
display: block;
visibility: hidden;
height: 0.1px;
font-size: 0.1em;
line-height: 0;
clear: both;
}
この内容を、form.css として保存しています(´・ω・`)
これを適用すると以下のようになります。

CSS Nite LP6 でのメモ内容
6月27日(土)にタイミング的に丁度いけそうでしたので、CSS Nite LP6 に行ってきました。
以下は会場でメモしていた内容です。
SOY CMS (http://www.soycms.net/)
- 記事とCMSの関連付けを自分で行うので複数の箇所を同時に更新ができる。
- システム全体のアカウントと記事を更新する用のアカウントが作れる。
- 記事には予めひな型を入れておくことができる。
+カスタムフィールドもあり(画像アップも) - 記事にラベルを付けて、ラベルを貼り付け先と連動させる。
- SOY App → 独立したアプリケーション
Inquiry(フォーム) / Mail(一括配信) / Board(掲示板)
Inquiry と Mail との間で連動もできる。 - SOY CMS の管理画面も同じシステムなのでカスタマイズが出来る。
- 動的出力(記事数: 数百ぐらいが限度)
Web Release2 (http://www.frameworks.co.jp/)
- 静的生成
- 「Variety Japan」 1.5ヶ月で公開。
データとデザインを同時に入れていくことができた。 - CSS・PHP・Javascript などアスキーならなんでも出力できる。
- 日産のサイト
XMLを生成してFlash にテンプレートに読み込んで表示している。 - (車のカタログの)オプションの部分
→ CSV でデータをインポートして WebRelease2 で XMLに出力している。
→ オンライン見積もりと連動も。1車種あたり 300~400のXMLファイル。 - XMLデータをHTMLに変換し Flash に対応していないブラウザの為の静的コンテンツを生成した。
CMS Designer (http://cms.al-design.jp/)
- 部分的に取り込めるCMS
- 入力項目の定義をXMLファイルで行う。
→ アップすることでフォームが構築される。 - XSLでデータを絞り込んだりすることができる。
通常のデザインの最上部・最下部にPHPコードを1行追加する。 - 日時指定公開 / 終了 設定
- ユーザー権限
→ (記事の)削除できる / 出来ない - ページキャッシュ
→ 静的ファイルを生成。生成されている場合にはHTMLを読み出して表示する。
RCMS (http://www.r-cms.jp/)
- SaaS版が主力。
- Google サイトマップ
→ 6種類ある。ニュースや地図など。 - PC向けのページは HTML4.0 出力 XHTMLではない。
- 1,500万PV/月
※ SaaS版。最大で 100万PV/月に設定されている。
a-blog CMS (http://www.a-blogcms.jp/)
- php で「プラグイン」を自作できるように。
- カスタムフィールド
→ 管理画面のHTMLファイルを編集すると反映される。
スコアボード等の表示にあわせたカスタムフィールドレイアウトが可能。 - メールフォーム
→ モジュールを分割してページを作る。(ステップ) - ユーザーエージェント / ユーザーID / カテゴリーID などにより表示ルールを変更する事ができる。
→ モバイルでは表示件数を3件に PC では5件に。 - テンプレートとしてHTMLファイルをディレクトリに入れて部分的に堂的な更新を追加できる。
最終的に、会場の挙手によるMVP は a-blog CMS に決まっていましたが、私が挙手をしたのは CMS Designer だったように記憶しています。
twitter で tsudoる – つどったー 作ったよ!
なんとなく土曜日に ついったーで人集める事を「tsudoる」って言えばいいんじゃね? と適当なことを考えてたら、
RT でドンドン「tsudoい」にフォローできたらなんて楽なんだろう。
と暴走してドメインまでとっちゃった。ので、折角なので作ってみた。
ドンッ! tsudotter.com
まず、アカウント名と集める内容を記入して「集まれー!」ってボタンをクリック。すると、@tsudotter から @メッセージが届くので、そのメッセージを RT(retweet)しよう!すると、自動的に登録される。
それを見た、他の人も参加したければ RT していけば参加完了。
RTするたびに、「登録(フォロー)」と「削除」のトグルになっています。返信で状況が送られてくるのでご安心。さらには参加者リストも一緒に送られてくるURLをクリックすればでてくるよ!
見ればわかるけれど、つくりは簡単。別にRTじゃなくとも、英数字6文字の組み合わせさえ入って @tsudotter 宛にメッセージ(DM除く)をすれば、cron でひっかけて英数字6文字のidを参照して登録と削除を繰り返してるだけです。
PINOKO という MMORPG コミュニティサイト
PINOKOというコミュニティサイト(サイトでは SNS としていましたが、今やその影も薄いですし SNS と呼べるような状態でもないのでコミュニティ)を作って運営しています。

運営をはじめて4年経っているわけですが、phpプログラムを書き出した頃に作ったものなので色々な意味で恥ずかしいコードだったりします。
今日はそんなPINOKOについて。
PINOKOって何?
当時、ミクシィが出始めた頃で色々な形態のSNSがぽつぽつ出ていました。そんな中、自分達が深くハマっていた MMORPG の FinalFantasy XI のSNSを作ってみよう!としたのが始まりです。
また当時、ゲームの中でパーティと呼ばれるグループ行動でモンスターを倒し経験値を得てレベルを上げる仕組みの中で「参加希望」という状態をする事は出来ても、参加者を募集するという事が出来ませんでした。(今は、様々な手段が用意されていますが関係の無い話なので省略します)
そういった仕組みを SNS の枠組みの中でウマく作れないか?という事も一つの大きな要素としていました。(これは結果的に失敗しました。)
PINOKOをやって良かったこと
恐らく、自分史上はじめて他人と共同作業で作った何か、なんじゃないかと思います。また、コードを書くにあたって調べまくっては猿のように書いていました。兎に角動くものを短時間で作り上げたのは初めてでした。
ほぼ放置となってしまった今も、コードを覗いては少しずつ フレームワーク などに置換えていくような遊びをしています。
そろそろ…
「そろそろ…」というと、飽きっぽいからと怒られるんですが、FinalFantasy XIV が発表になり新しく MMORPG が出る事が決定しているので、また違うサイトをしたいなあと思ったりもしています。
技術的な話
PHP + PostgreSQL な環境で作られています。PostgreSQL が動かせるレンタルサーバーが少ないので、とりあえず自宅で稼動していますが、ファンがうるさかったり電気代がかかったり、サーバーのスペックが重く、キビキビとした動作が出来ないので MySQL に移してレンタルサーバーに入れる予定です。
そのタイミングで、機能的にもシェイプアップできればなぁと思っています。
CSS Nite LP, Disk 6
CSS Nite の存在を知ってからなかなかタイミングが合わず申込みができなかったんだけれど、今回タイミングがあったので申込みました!

6月27日(土) 13:50から18:40まで。国産CMS祭という事で現在携わっているシステムのCMS置換えを頭にいれつつ、しっかり聞いてきたいと思います。
(*´Д`*)いえーい
→ CSS Nite LP, Disk 6(LP6)「CMSリベンジ編」(2009年6月27日開催):国内産CMSに特化したセミナー


