CodeIgniterの学習 32 - xajaxで住所/郵便番号検索サンプルを作ってみる(住所郵便番号検索作成その4 )

(仕事が忙しいので、学習の更新は少なめなりよ。チェックしてないアニメがry)


今日は以前CodeIgniterに組み込んだxajaxライブラリ(http://d.hatena.ne.jp/dix3/20080924/1222195390)と、
以前学習したテーブル生成クラス(http://d.hatena.ne.jp/dix3/20081009/1223487950)をつかって、
住所/郵便番号検索サンプルを作ってみる。


郵便番号の元データは、http://d.hatena.ne.jp/dix3/20081024/1224783465 の方法で取り込み済み。


(xajaxの説明を簡易にするため操作性周り、エラー処理周り、バリデーション周り、csrf(xss)周りの処理は入れていない。ページネーションもまだ。)

画面

こんな感じ、生成部分をコントローラに書いているが、
本当はこれをヘルパの呼び出しだけで簡単に使えるようにしたい。


A1:郵便番号を一部入力して、住所検索ボタンを押す


A2:検索された! xajax経由で結果の一覧がinnerHTMLで描き変わって表示される


A3:一覧で選択すると、正しい郵便番号と住所が格納される




B1:今度は住所を入れてみる、わざと部分的に住所を入れる


B2:検索された! xajax経由で結果の一覧がinnerHTMLで描き変わって表示される


B3:一覧で選択すると、正しい郵便番号と住所が格納される


ソース

忙しいので解説は手抜き。
ソースは全部貼っておく。(xajaxの導入ついては以前のエントリhttp://d.hatena.ne.jp/dix3/20080924/1222195390を参照)


1:コントローラ application/controllers/zipsearchsample.php
実験コントローラを作った。
xajaxの基本みたいな書き方。

php側で処理を記述して、

  • $objResponse -> Assign( "zipcodelist", "innerHTML", $this -> table -> generate() ); //動的に生成
  • $objResponse -> Assign( "zipcodelist", "className", '' ); //display:noneのcssクラスを解除

みたいに id , 属性 ,変更する値 を指定してあげると、ニュルっとajaxで画面が描き変わってくれる。

<?php if ( ! defined( 'BASEPATH' ) ) exit( 'No direct script access allowed' );
// 郵便番号、住所検索サンプルコントローラ
// xajaxで呼び出してみる実験 ページネーションはまだ
class Zipsearchsample extends Controller {
  // コンストラクタ
  function Zipsearchsample()
  {
    parent :: Controller(); 
    // urlヘルパ
    $this -> load -> helper( 'url' ); 
    // フォームヘルパ
    $this -> load -> helper( 'form' );
  } 
  // デフォルトインデックス
  function index()
  { 
    // xajaxを有効に
    $this -> load -> library( 'xajax' );
    $this -> xajax -> registerFunction( array( '_getZipcode', &$this, '_getZipcode' ) );
    $this -> xajax -> registerFunction( array( '_getAddress', &$this, '_getAddress' ) );
    $this -> xajax -> processRequest(); 
    // 中身のテンプレート用
    $data['title'] = "郵便番号、住所検索をxajaxで呼び出してみる実験、ページネーションはまだ"; 
    // ヘッダ用部分xajaxタグの生成
    $tpl['xajax_js'] = $this -> xajax -> getJavascript( base_url() ); 
    // 外枠のテンプレートに、タスクリストのビューをはめ込む
    $tpl["main_content"] = $this -> load -> view( "zipsearchsample_index", $data , true );

    $this -> load -> view( 'base_view', $tpl );
  } 
  // xajaxで郵便番号の取得
  function _getZipcode( $pref = '' , $city = '' , $street = '' )
  { 
    // xajax用(ボタン押下時のイベント)
    $objResponse = new xajaxResponse(); 
    // 郵便番号←→住所変換ライブラリのロード
    $this -> load -> library( 'zipcode', 'array' ); 
    // HTML テーブルクラスのロード
    $this -> load -> library( 'table' ); 
    // 入力された住所から郵便番号データを取得
    $data = $this -> zipcode -> getZipcode( $pref , $city , $street ); 
    // テーブルのヘッダ生成
    $this -> table -> set_heading( '郵便番号', '都道府県', '市区町村', '町名・番地', '選択' ); 
    // テーブルの生成
    foreach ( $data as $row ) {
      // javascriptをここに書くのは苦しい
      // 本当はdocument.getElementById('hoge').valueとかの取得は、外部に短縮名で呼び出せるファンクションを定義しておく
      $js = "onclick=\"javascript:document.getElementById('zipcode').value ='" . $this -> input -> xss_clean( trim( $row['zipcode'] ) ) .
        "';document.getElementById('pref').value='" . $this -> input -> xss_clean( trim( $row['pref'] ) ) . 
        "';document.getElementById('city').value ='" . $this -> input -> xss_clean( trim( $row['city'] ) ) . 
        "';document.getElementById('street').value ='" . $this -> input -> xss_clean( trim( $row['street'] ) ) . 
        "';document.getElementById('zipcodelist').innerHTML='';\"" ;
      $this -> table -> add_row( $row['zipcode'] ,
        $row['pref'] ,
        $row['city'],
        $row['street'],
        form_button( array( 'value' => $row['zipcode'], 'type' => 'button' ), '選択', $js ) // ボタンクリックで郵便番号を格納する
        );
    } 
    // SomeElementId とついたID内をinnerHTML書き換えで、入れ替える
    $objResponse -> Assign( "zipcodelist", "innerHTML", $this -> table -> generate() ); //動的に生成
    $objResponse -> Assign( "zipcodelist", "className", '' ); //display:noneのcssクラスを解除
    return $objResponse;
  } 
  // xajaxで住所の取得
  function _getAddress( $zipcode = '' )
  { 
    // xajax用(ボタン押下時のイベント)
    $objResponse = new xajaxResponse(); 
    // 郵便番号←→住所変換ライブラリのロード
    $this -> load -> library( 'zipcode', 'array' ); 
    // HTML テーブルクラスのロード
    $this -> load -> library( 'table' ); 
    // 入力された住所から郵便番号データを取得
    $data = $this -> zipcode -> getAddress( $zipcode ); 
    // テーブルのヘッダ生成
    $this -> table -> set_heading( '郵便番号', '都道府県', '市区町村', '町名・番地', '選択' ); 
    // テーブルの生成
    foreach ( $data as $row ) {
      // javascriptをここに書くのは苦しい
      // 本当はdocument.getElementById('hoge').valueとかの取得は、外部に短縮名で呼び出せるファンクションを定義しておく
      $js = "onclick=\"javascript:document.getElementById('zipcode').value ='" . $this -> input -> xss_clean( trim( $row['zipcode'] ) ) .
        "';document.getElementById('pref').value='" . $this -> input -> xss_clean( trim( $row['pref'] ) ) . 
        "';document.getElementById('city').value ='" . $this -> input -> xss_clean( trim( $row['city'] ) ) . 
        "';document.getElementById('street').value ='" . $this -> input -> xss_clean( trim( $row['street'] ) ) . 
        "';document.getElementById('zipcodelist').innerHTML='';\"" ;
      $this -> table -> add_row( $row['zipcode'] ,
        $row['pref'] ,
        $row['city'],
        $row['street'],
        form_button( array( 'value' => $row['zipcode'], 'type' => 'button' ), '選択', $js ) // ボタンクリックで郵便番号を格納する
        );
    } 
    // SomeElementId とついたID内をinnerHTML書き換えで、入れ替える
    $objResponse -> Assign( "zipcodelist", "innerHTML", $this -> table -> generate() ); //動的に生成
    $objResponse -> Assign( "zipcodelist", "className", '' ); //display:noneのcssクラスを解除
    return $objResponse;
  }
} //Endofclass

/*
CREATE TABLE zipcode (
id INTEGER(10) UNSIGNED NOT NULL auto_increment,
code VARCHAR(6) NOT NULL,          #  1. 全国地方公共団体コード(JIS X0401、X0402)……… 半角数字
old_zipcode VARCHAR(5) NOT NULL,   #  2. (旧)郵便番号(5桁)…… 半角数字、空白トリム
zipcode VARCHAR(7) NOT NULL,       #  3. 郵便番号(7桁)………… 半角数字
kana_pref VARCHAR(64) NOT NULL,    #  4. 都道府県名 ………… 全角カタカナ(コード順に掲載)
kana_city VARCHAR(127) NOT NULL,   #  5. 市区町村名 ………… 全角カタカナ(コード順に掲載)
kana_street VARCHAR(127) NOT NULL, #  6. 町域名 ……………… 全角カタカナ(五十音順に掲載)
pref VARCHAR(64) NOT NULL,         #  7. 都道府県名 ………… 漢字(コード順に掲載)
city VARCHAR(127) NOT NULL,        #  8. 市区町村名 ………… 漢字(コード順に掲載)
street VARCHAR(127) NOT NULL,      #  9. 町域名 ……………… 漢字(五十音順に掲載)
f1 INTEGER(1) UNSIGNED NOT NULL DEFAULT 0,   # 10. 一町域が二以上の郵便番号で表される場合の表示 (「1」は該当、「0」は該当せず)
f2 INTEGER(1) UNSIGNED NOT NULL DEFAULT 0,   # 11. 小字毎に番地が起番されている町域の表示(「1」は該当、「0」は該当せず)
f3 INTEGER(1) UNSIGNED NOT NULL DEFAULT 0,   # 12. 丁目を有する町域の場合の表示 (「1」は該当、「0」は該当せず)
f4 INTEGER(1) UNSIGNED NOT NULL DEFAULT 0,   # 13. 一つの郵便番号で二以上の町域を表す場合の表示(「1」は該当、「0」は該当せず)
f5 INTEGER(1) UNSIGNED NOT NULL DEFAULT 0,   # 14. 更新の表示(「0」は変更なし、「1」は変更あり、「2」廃止(廃止データのみ使用))
f6 INTEGER(1) UNSIGNED NOT NULL DEFAULT 0,   # 15. 変更理由 (「0」は変更なし、「1」市政・区政・町政・分区・政令指定都市施行、「2」住居表示の実施、「3」区画整理、「4」郵便区調整等、「5」訂正、「6」廃止(廃止データのみ使用))
del_flg INTEGER(1) UNSIGNED NOT NULL DEFAULT 0,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
modified TIMESTAMP NULL ,
PRIMARY KEY(id)
);

CREATE INDEX idx1_zipcode on zipcode (zipcode,del_flg);
CREATE INDEX idx2_zipcode on zipcode (pref,del_flg);
CREATE INDEX idx3_zipcode on zipcode (pref,city,del_flg);
CREATE INDEX idx4_zipcode on zipcode (pref,city,street,del_flg);
CREATE INDEX idx5_zipcode on zipcode (city,del_flg);
CREATE INDEX idx6_zipcode on zipcode (city,street,del_flg);
CREATE INDEX idx7_zipcode on zipcode (street,del_flg);
CREATE INDEX idx8_zipcode on zipcode (f6,del_flg);
CREATE INDEX idx9_zipcode on zipcode (old_zipcode,del_flg);
*/


/**
 * End of file zipsearchsample.php
 */
/**
 * Location: ./application/controllers/zipsearchsample.php
 */
 ?>


2:中身ビュー application/views/zipsearchsample_index.php
簡単のためいろいろそぎ落としている。

<h3><?= $title ?></h3>
<form>
<label>郵便番号</label>
<input type="text" name="zipcode" id="zipcode" value="" size="10" />
<input type="button" name="address_search" id="address_search" value="住所検索" onclick="javascript:xajax__getAddress(document.getElementById('zipcode').value);" />


<label>都道府県</label>
<!-- フォームヘルパの拡張 -->
<?=form_pref('pref','','pref');?>

<label>市町村名</label>
<input type="text" name="city" id="city" value="" size="30" />

<label>住所</label>
<input type="text" name="street" id="street" value="" size="60" />
<input type="button" name="zipcode_search" id="zipcode_search" value="郵便番号検索" onclick="javascript:xajax__getZipcode(document.getElementById('pref').value, document.getElementById('city').value , document.getElementById('street').value );" />

<!-- このidの中がinnerHTMLで変化する -->
<div id="zipcodelist" class="none"></div>

</form>



3:フォームヘルパの拡張 application/helpers/MY_form_helper.php
都道府県名を作るのが面倒だったから。

<?php if ( !defined( 'BASEPATH' ) ) exit( 'No direct script access allowed' );
//上略
if ( ! function_exists( 'form_pref' ) ) {
  // 都道府県のプルダウン生成
  // valueも都道府県名なのが微妙だが気にしない
  function form_pref( $name = '', $selected = array(), $id = '', $extra = '' )
  {
    $options = array();
    $p_arr = array( "北海道", "青森県", "岩手県", "宮城県", "秋田県", "山形県", "福島県", "茨城県", "栃木県", "群馬県", "埼玉県", "千葉県", "東京都", "神奈川県", "山梨県", "長野県", "新潟県", "富山県", "石川県", "福井県", "岐阜県", "静岡県", "愛知県", "三重県", "滋賀県", "京都府", "大阪府", "兵庫県", "奈良県", "和歌山県", "鳥取県", "島根県", "岡山県", "広島県", "山口県", "徳島県", "香川県", "愛媛県", "高知県", "福岡県", "佐賀県", "長崎県", "熊本県", "大分県", "宮崎県", "鹿児島県", "沖縄県", "国外/その他" );

    foreach( $p_arr as $v ) {
      $options[$v] = $v;
    }
    if ( $id ) {
      $extra = ' id="' . $id . '" ' . $extra ;
    }
    return form_dropdown( $name, $options, $selected , $extra );
  }
}

/* End of file MY_form_helper.php */
/* Location: ./application/helpers/MY_form_helper.php */
 ?>



4:作りかけのライブラリ application/libraries/Zipcode.php
前回のエントリでコントローラを作りかけたソースをライブラリに移動した。
郵便番号/住所検索結果レコードをarray,serialize,JSONの形式で取得出来るようにしているつもり。今回はarrayで取得。
JSONライブラリについては、昨日のエントリを参照)

<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
//郵便番号←→住所検索ライブラリ 制作中
class Zipcode{
  var $CI ;
  var $errmsg='';
  var $return_type;//戻り値のタイプarray,json,serialize
  var $data;

  // コンストラクタ
  function Zipcode($return_type='array')
  {
    $this -> CI = &get_instance();
    $this -> return_type = $return_type;
  } 
  // 住所→郵便番号検索
  function getZipcode( $pref='', $city='' ,$street = '', $limit = 30, $offset = 0)
  {
    //ここでxssフィルタしておく
    $pref = $this -> CI -> input -> xss_clean( $pref );
    $city = $this -> CI -> input -> xss_clean( $city );
    $street = $this -> CI -> input -> xss_clean( $street );
    $data = array();
    // リミット
    $limit = is_integer( $limit ) ? ( int ) $limit  : 30 ; 
    // オフセット
    $offset = is_integer( $offset ) ? ( int ) $offset : 0 ; 

    // 検索条件
    if($pref){
      $this -> CI -> db -> like( 'pref', $pref, 'after' ); 
    }
    if($city){
      $this -> CI -> db -> like( 'city', $city, 'after' ); 
    }
    if($street){
      $this -> CI -> db -> like( 'street', $street, 'after' ); 
    }
    //並び順
    $this -> CI -> db -> order_by('zipcode');
    // データ取得のリミットとオフセット
    $this -> CI -> db -> limit( $limit, $offset ); 

    // データ取得
    $query = $this -> CI -> db -> get( 'zipcode' );

    $cnt = $query -> num_rows();
    if ( $cnt ) {
      foreach( $query -> result_array() as $k => $row ) {
        foreach( $row as $col => $val ) {
          $data[$k][$col] = $val;
          
        }
      }
    }else{
      $this->setErrmsg("見つからない");
    }
    
    $this->setData($data);
    //戻り値の変換(array or serialize or JSON)
    return $this->returnData();
  }

  // 郵便番号→住所検索
  function getAddress( $zipcode = null, $limit = 30, $offset = 0)
  {
    $zipcode = $this -> CI -> input -> xss_clean( $zipcode ); //ここでxssフィルタしておく
    $regexp = "#^(\d{3})-?(\d{0,4})$#iu";
    $zipcode = mb_convert_kana( $zipcode, "a" ); //全角数字も半角数字に変換して問い合わせる
    $data = array();

    if ( !preg_match( $regexp, $zipcode ) ) {
      // 変な郵便番号は認めませんよ
      $this->setErrmsg("正しい郵便番号を入れてくださいねぇ");
    }else {
      // パラメータのフィルタをしておく
      // 郵便番号
      $zipcode = preg_replace( $regexp, "\\1\\2", $zipcode ); 

      // リミット
      $limit = is_integer( $limit ) ? ( int ) $limit  : 30 ; 
      // オフセット
      $offset = is_integer( $offset ) ? ( int ) $offset : 0 ; 

      // 検索条件
      $this -> CI -> db -> like( 'zipcode', $zipcode, 'after' ); 
      //並び順
      $this -> CI -> db -> order_by('zipcode');
      // データ取得のリミットとオフセット
      $this -> CI -> db -> limit( $limit, $offset ); 

      // データ取得
      $query = $this -> CI -> db -> get( 'zipcode' );
      
      $cnt = $query -> num_rows();
      if ( $cnt ) {
        foreach( $query -> result_array() as $k => $row ) {
          foreach( $row as $col => $val ) {
            $data[$k][$col] = $val;
            
          }
        }
      }else{
        $this->setErrmsg("見つからないっす");
      }
    } 
    $this->setData($data);
    return $this->returnData();
  }
  //戻り値の変換(array or serialize or JSON)
  function returnData(){
    //値の返送
    switch($this->return_type)
    {
      case "array":
        //配列で返す
        return $this->getData();
        break;
      case "serialize":
        //シリアライズして返す
        return serialize($this->getData());
        break;
      case "json":
        //JSON形式で返す
        $this -> CI -> load -> helper( 'json' );
        return json_encode($this->getData());
        break;
      default:
        return $this->getData();
        break;
    }
  }
  //エラーメッセージセット
  function setErrmsg($msg='')
  {
    $this->errmsg = $msg;
  } 
  //エラーメッセージ取得
  function getErrmsg()
  {
    return $this->errmsg;
  } 
  //データセット
  function setData($data){

    $this->data = $data;
  }
  //データ取得
  function getData()
  {
    return $this->data;
  } 

} //Endofclass


/*
CREATE TABLE zipcode (
id INTEGER(10) UNSIGNED NOT NULL auto_increment,
code VARCHAR(6) NOT NULL,          #  1. 全国地方公共団体コード(JIS X0401、X0402)……… 半角数字
old_zipcode VARCHAR(5) NOT NULL,   #  2. (旧)郵便番号(5桁)…… 半角数字、空白トリム
zipcode VARCHAR(7) NOT NULL,       #  3. 郵便番号(7桁)………… 半角数字
kana_pref VARCHAR(64) NOT NULL,    #  4. 都道府県名 ………… 全角カタカナ(コード順に掲載)
kana_city VARCHAR(127) NOT NULL,   #  5. 市区町村名 ………… 全角カタカナ(コード順に掲載)
kana_street VARCHAR(127) NOT NULL, #  6. 町域名 ……………… 全角カタカナ(五十音順に掲載)
pref VARCHAR(64) NOT NULL,         #  7. 都道府県名 ………… 漢字(コード順に掲載)
city VARCHAR(127) NOT NULL,        #  8. 市区町村名 ………… 漢字(コード順に掲載)
street VARCHAR(127) NOT NULL,      #  9. 町域名 ……………… 漢字(五十音順に掲載)
f1 INTEGER(1) UNSIGNED NOT NULL DEFAULT 0,   # 10. 一町域が二以上の郵便番号で表される場合の表示 (「1」は該当、「0」は該当せず)
f2 INTEGER(1) UNSIGNED NOT NULL DEFAULT 0,   # 11. 小字毎に番地が起番されている町域の表示(「1」は該当、「0」は該当せず)
f3 INTEGER(1) UNSIGNED NOT NULL DEFAULT 0,   # 12. 丁目を有する町域の場合の表示 (「1」は該当、「0」は該当せず)
f4 INTEGER(1) UNSIGNED NOT NULL DEFAULT 0,   # 13. 一つの郵便番号で二以上の町域を表す場合の表示(「1」は該当、「0」は該当せず)
f5 INTEGER(1) UNSIGNED NOT NULL DEFAULT 0,   # 14. 更新の表示(「0」は変更なし、「1」は変更あり、「2」廃止(廃止データのみ使用))
f6 INTEGER(1) UNSIGNED NOT NULL DEFAULT 0,   # 15. 変更理由 (「0」は変更なし、「1」市政・区政・町政・分区・政令指定都市施行、「2」住居表示の実施、「3」区画整理、「4」郵便区調整等、「5」訂正、「6」廃止(廃止データのみ使用))
del_flg INTEGER(1) UNSIGNED NOT NULL DEFAULT 0,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
modified TIMESTAMP NULL ,
PRIMARY KEY(id)
);

CREATE INDEX idx1_zipcode on zipcode (zipcode,del_flg);
CREATE INDEX idx2_zipcode on zipcode (pref,del_flg);
CREATE INDEX idx3_zipcode on zipcode (pref,city,del_flg);
CREATE INDEX idx4_zipcode on zipcode (pref,city,street,del_flg);
CREATE INDEX idx5_zipcode on zipcode (city,del_flg);
CREATE INDEX idx6_zipcode on zipcode (city,street,del_flg);
CREATE INDEX idx7_zipcode on zipcode (street,del_flg);
CREATE INDEX idx8_zipcode on zipcode (f6,del_flg);
CREATE INDEX idx9_zipcode on zipcode (old_zipcode,del_flg);

*/


/* End of file Zipcode.php */
/* Location: ./application/libraries/Zipcode.php */
 ?>


5:外枠ビュー application/views/base_view.php
あまり変えていない。(以前のエントリのやつで動く。)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<meta name="keywords" content="ここがキーワード" />
<meta name="description" content="ここに説明が入る" />
<title><?php if(isset($page_title)){echo $page_title ;}?></title>
<?php if(isset($jquery_js)){echo "\n" . $jquery_js ;}?>
<?php if(isset($xajax_js)){echo "\n" . $xajax_js ;}?>
<?php if(isset($validation_js)){echo "\n" . $validation_js ;}?>
<?php if(isset($array_js)){foreach((array) $array_js as $js_script ){ echo "\n" . $js_script; }}?>
<link href="/css/style.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<!-- container //-->
<div id="container">
    <!-- header //-->
    <div id="header">
        <div id="top">
            <!-- タイトル -->
            <h1><span id="title">CodeIgniterの学習</span><span id="subtitle"><?php if(isset($sub_title)){echo " - " . $sub_title ;}?></span></h1>
            <!-- スローガン -->
            <h2>dix3の練習サンドボックス 適当に作ったけどベースにつかえるかもね。</h2>
        </div>
        <!-- メインメニュー -->
        <!-- todo:後で -->
        <div id="menu">
            <ul>
            <li><a href="/" class="current">ホーム</a></li>
            <li><a href="/zipsearchsample/">郵便番号住所検索テスト</a></li>
            <li><a href="/tasklist/">タスク一覧</a></li>
            <li><a href="/tasklist/edit/">タスク追加</a></li>
            <li><a href="/tasklist/imgtest/">画像変換テスト</a></li>
            <li><a href="/flickr">Flickrのテスト</a></li>
            <li><a href="/auth/logout.html">ログアウト</a></li>
            </ul>
        </div>
    </div>
    <!--// header -->

    <!-- leftblock //-->
    <div id="leftblock">
        <div>
            <p>ようこそ!<?php echo ""; //getUserName();//freakauth用 ?>ちゃん</p>
            <p class="yellow">締切り前のタスクが1件あります</p>
            <p class="red">期限切れのタスクが2件あります</p>
        </div>
        <div>
            <!-- サブメニュー -->
            <ul id="submenu">
                <li><a href="#">セッションの動作テスト</a></li>
                <li><a href="#">キャプチャの動作テスト</a></li>
                <li><a href="#">グラフの動作テスト</a></li>
                <li><a href="#">なんとかかんとかの動作テスト</a></li>
            </ul>
        </div>
        <?php if(isset($calendar)){ ?>
            <!-- calendar //-->
            <div class="calendar"><?=$calendar?></div>
            <!--// calendar -->
        <?php } ?>
    </div>
    <!--// leftblock -->
    <!-- rightblock //-->
    <div id="rightblock">
        <!-- breadcrumb //-->
        <div id="breadcrumb">
            <a href="#">ホーム</a> &gt; <a href="#">CodeIgniterの学習</a> &gt; <a href="#">ここはブレッドクラム</a>
        </div>
        <!--// breadcrumb -->
        <!-- content //-->
        <div id="content">
            <!-- main_content //-->
            <?=$main_content?>
            <!--// main_content -->
        </div>
        <!--// content -->
    </div>
    <!--// rightblock -->
    <!-- footer //-->
    <div id="footer">
        &copy; 2008 dix3 ヌル日記 <a href="http://d.hatena.ne.jp/dix3/">http://d.hatena.ne.jp/dix3/</a>
    </div>
    <!--// footer -->
</div>
<!--// container -->

<!-- Google Analytics //-->
<!-- todo:リリースモード且つ公開ページには ここにgoogle_analyticsヘルパを設置する -->
<!--// Google Analytics -->
</body>
</html>


6:css html/css/style.css
これも以前と変わっていないけど貼っておく。

/* ボディ */
body{
  background:#fff;
  font-family: 'メイリオ','Meiryo','Hiragino Kaku Gothic Pro',
  'ヒラギノ角ゴ Pro W3','Osaka','MS Pゴシック',Arial,Verdana,sans-serif;
  font-size:14px;
  line-height:1.4em;
  margin: 0 auto;
}
h1, h2{
  color: #555;
  font-size:1.6em;
  border-bottom:1px solid #ddd;
  padding: 20px 0 1px 2px;
  width:50%;
}
h3, h4{
  color:  #555;
  font-size:1.2em;
  padding: 0 0 4px 2px;
}
hr{
  border:0;
  border-bottom: 1px solid #ddd;
  height: 1px;
}
a{
 text-decoration:none;
}
a:link, a:visited{
  color: #4169e1;
}
a:hover{
  color: #ff6600;
}
li{
  line-height: 1.6em;
}
/* 作成途中のメモ用 */
.memo{
	color:#ff0000;
	font-size:16px;
}
#content{
/* 赤枠は後で消す */
/*border:dotted 1px #ff0000;*/
}
/* フォーム */
#content form{
  padding:8px;
  width:80%;
  background:#f2f2f2;
}
/* フォーム内のラベル */
form label{
  margin:3px 0 2px 0;
  display:block;
  font-weight:bold;
}
#content input{
	padding:2px 3px;
}
#content div{
	padding:4px;
}
/* テーブル */
#content table{
	border-collapse: collapse;
	background:#ddd;
	border:1px solid #ccc;
}
#content  th{
	border:1px solid #ccc;
	text-align:center;
	padding:5px;
}
#content  td{
	border:1px solid #ccc;
	background:#f9f9f9;
	padding:5px;
}
/* ヘッダ */
#header{
  padding: 0 0 4px 0;
  border-bottom: 1px solid #ddd;
  background : transparent;
}
/* フッタ */
#footer{
  clear : both;
  text-align:right;
  margin : 0;
  padding : 10px;
  color : #777;
  border-top : 1px solid #ddd;
  
}
/* トップ */
#top {
  padding:10px;
  background : transparent;
  height:32px;
}
/* タイトル */
#top h1 {
  font-size: 1.7em;
  font-weight: bold;
  margin : 0 10px;
  padding : 18px 0 0 0;
  letter-spacing : 1px;
  color : #a87b7b;
  border:0;
}
/* サブタイトル */
#subtitle{
  color: #666;
}
/* スローガン */
#top h2 {
  font-size : 0.9em;
  margin : 1px 30px;
  padding : 0;
  letter-spacing : 0;
  color : #868686;
  border : 0;
}
/* 大外の枠 */
#container{
  margin : 2px auto;
  width : 97%;
  color: #4F5155;
  border:1px solid #ccc;
}
/* メニュー */
#menu {
  text-align:right;
  margin : 0;
  padding : 0;
  height : 34px;
}
#menu li {
  list-style : none;
  display : inline;
  line-height : 34px;
}
#menu li a {
  text-decoration : none;
  margin : 0;
  padding : 9px 15px 10px 15px;
  font-weight : bold;
  color : #fff;
  background:#bc8f8f;
  border-left:1px solid #fff;
}
#menu li a:hover {
  color : #222;
  background : #f8cbcb;
  margin : 0;
}
#menu li a.current{
  color : #fff;
  background : #eec1c1;
  margin : 0;
}
/* 左ブロック */
#leftblock{
  float: left;
  margin: 0;
  padding: 4px ;
  width: 20%;
  height: auto;
  
}
#leftblock p{
  width: 100%;
	padding: 3px 4px;
}
/* 右ブロック */
#rightblock{
  float: right;
  width:75%;
  min-width: 400px;
  padding: 12px;
  border-left: 1px solid #ddd;
  line-height: 145%;
}
/* サブメニュー */
#submenu{
  width:96%;
  margin:0;
  padding:2px 0 0 18px;
  font-size:0.875em;
	border:1px solid #ffffcc;
	background:#ffffdd;
}
#submenu li{
  padding:0;
  margin:0;
  line-height:100%;
}
#submenu a:link, #submenu a:visited{
  margin: 3px 0;
  padding: 4px 3px 3px 8px;
  text-decoration: underline;
  display: block;
}
/* ブレッドクラム */
#breadcrumb {
  padding: 8px 0 14px 0;
}
#breadcrumb a:link, #breadcrumb a:visited{
	text-decoration: underline;
  color: #777;
}
#breadcrumb a:hover{
  color: #ff6600;
}
/* ラベルの色 */
.info{
  padding: 10px;
  margin:4px 0;
  width:70%;
}
.box{
 padding:4px;
 width:80%;
}
.red{
  background: #ffbbcc;
  border:1px solid #ffbbcc;
}
.green{
  background: #b8e08f;
  border:1px solid #bfdb58;
}
.yellow{
  background: #f6e080;
  border:1px solid #ffd77d;
}
.blue{
  background: #c1ecfa;
  border:1px solid #b7e2f0;
}
.gray{
  background-color: #f9f9f9;
  border:1px solid #f1f1f1;
}
.txt_red{
  color:#ff0000;
}
/* カレンダー */
.calendar {
	margin-top:8px;
	font-size:1.1em;
}
.calendar table{
	border-collapse: collapse;
	background:#bc8f8f;
	border:1px solid #ccc;
}
.calendar  th{
	border:1px solid #ccc;
	text-align:center;
	color:#fff;
	padding:5px;
}
.calendar  th a{
	color:#fff;
}
.calendar  th a:hover{
	color:#ff6600;
}
.calendar  td{
	border:1px solid #ccc;
	background:#fcfcfc;
	padding:6px;
	text-align:center;
}
/* カレンダーの週 */
.cal_weekrow td{
	background:#a69090;
	color:#fff;
}
.cal_today{
	text-decoration:underline;
	color:#ff6600;
}
p.pagination{
	margin:3px 0;
	padding:0;
}
.pagination a , .pagination b{
	margin-left:2px;
}
/*画面非表示*/
.none{
  display:none;
}
/*フォーム内エラー文言は赤字*/
form fieldset p{
  margin:0;
  padding:0px;
  color:#ff0000;
  font-size:0.875em;
  /*display:inline;*/
}
form fieldset{
  border:1px solid #ccc;
}
form em{
  color:#ff0000;
}
form input , form textarea{
  font-size:12px;
}



xajaxってイイネ。ちまちまjavascriptを記述するのがあほらしくなる。

ただ、内部的な動きを見るとちまちま作る方が無駄が少ないと思うけど。
(xajaxでリクエストが来たときは、必要な処理が終わったら途中で抜けさせないとね。)


次の更新はまた明後日くらいを目標に。

いい加減業務で使い始めたいなぁー。俺的にはまだまだ実験不足。

そういえばVersion 1.7.0になったね。そっちも試してみたい。