« google app engineで家計簿作り | トップページ | google app engineで家計簿3 »

2008年11月13日 (木)

google app engineで家計簿作り2

今日は最初にgoogle app engineのgvimの設定から。

function GoogleUpload()
  let s:nowDir = substitute(expand("%:p:h"),"c:\\app\\(.*\\)$","\\1","")
  execute "!python \"C:\\Program\ Files\\Google\\google_appengine\\appcfg.py\" update  ".s:nowDir
endfunction
cnorem <C-e> call GoogleUpload()<CR>

これが何がうれしいかというと、google app engineのソースを修正している際に
ノーマルモード状態から: 入力によりコマンドモードに移った後、 Ctrl+e入力で
現在のソースがあるディレクトリに対してappcfg.py upload を実行できるという
ものだ。
コマンドプロンプトを立ち上げておいてもいいのだが、appcfg.pyのフルパスを
入力するのが面倒だし、エディタから離れずにアップロードができるのは、
連続的にできるため、思考が途切れない。
普段の開発でもよく、svcコマンドやftpコマンドをこのようにキーマップに割り当てて
開発する。
コマンドモードに対してキーマップを割り振るのは比較的コマンドモードのキーは
割り当てられていないから、バッティングしないからである。

index.html

<html>
  <head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <title> 家計簿 </title>
 <script type="text/javascript" src="js/prototype-1.6.0.3.js"></script>
 <script type="text/javascript" src="js/common.js"></script>
 <script type="text/javascript" src="js/dateselect.js"></script>
 <script type="text/javascript" src="js/accountList.js"></script>
 <link href="css/account.css" rel="stylesheet" type="text/css">
 </head>
<body>
  <div>
    <input type="submit" value="項目編集" 
            onclick="
document.location.href='/category';"/>
    <input type="submit" value="一覧" 
           onclick="
document.location.href='/listaccount';"/>
  </div>
  <hr/>
  <div class="bold" id="totalAccount"></div>
  <form id="account" action="/" method="post">
    <div id="account_date">
    </div>
    <div>
      <span class="title" id="items_span"></span>
    </div>
    <div>
      <span class="title">費用</span>
      <input type="text" name="price" id="account_price" size="9"
                     
style="{ime-mode : disabled}"/>
    </div>
    <div><span class="title">内容</span>
      <input type="text" size="100" id="account_content"
               
name="content" style="vertical-align:top"/>
    </div>
    <input type="submit" value="送信" onclick="return dataSend()"/>
  </form>
  <div id="accountTitle"></div>
  <div id="accountTable"></div>
  <script type="text/javascript">
 function dataSend()
 {
 var a = new Ajax.Request( 
 "/addAccount",
 { 
 "method": "post",
 "parameters": Form.serialize("account"),
              onSuccess: function(request) { 
                $('account_content').value=""
                $('account_price').value=""
                setAccountData();            
 },
              onFailure: function(request) { 
 alert('読み込みに失敗しました');
 },
              onException: function (request) { 
 alert('読み込み中にエラーが発生しました');
 } 
 });
 return false;
 }
 function setAccountData()
 {
      setTotalAccount();
 var dateStr = $F('account_year')+"年"+$F('account_month')+"月"
                      
+$F('account_day')+"日";
 var tableStr = '<h3>'+dateStr+'の費用一覧 </h3>';
      $('accountTitle').html = tableStr;
      accountData.loadData();
 } 
 function setTotalAccount()
 {
 var a = new Ajax.Request( 
 "/gettotalaccount",
 { 
 "method": "get",
 "parameters": Form.serialize("account"),
              onSuccess: function(request) { 
                $('totalAccount').innerHTML=$F('account_year')+'年'+
         $F
('account_month')+'月の合計:'+
                  myFormatNumber(request.responseText) + '円';
 },
              onFailure: function(request) { 
 alert('読み込みに失敗しました');
 },
              onException: function (request) { 
 alert('読み込み中にエラーが発生しました');
 } 
 });
 }
 function setCategoriesData(categories)
 {
 if(categories.length == 0)
 {
 alert("初めてのご使用ですね。項目編集のボタンを押下して、" +
       "食費、交通費等の項目を設定してください。"
);
 return;
 }
      optStr = '項目<select name="category" id="category">';
 for (var i=0 ;i<categories.length;i++)
 {
        optStr += '<option value="'+categories[i].key+'" >'+
                                 categories
[i].name+'</option>';
 }
      optStr+='</select>';
      $("items_span").innerHTML = optStr;
 }
 function setCategories()
 {
 var a = new Ajax.Request( 
 "/getcategories",
 { 
 "method": "get",
              onSuccess: function(request) { 
                setCategoriesData(eval(request.responseText));
 },
              onFailure: function(request) { 
 alert('読み込みに失敗しました');
 },
              onException: function (request) { 
 alert('読み込み中にエラーが発生しました');
 } 
 });
 }
 var dateSelector = null;
 var accountData = null;
 document.observe('dom:loaded',function(){
    accountData = new AccountList('accountTable',"day","account");
    dateSelector = new DateSelector('account','account_date',
                                    setAccountData
);
    setCategories();
 });
 </script>
</body>
</html>

ではメインページのhtmlに移る。
昨日説明したとおり、テンプレートとしてindex.htmlを呼び出しているが、変数による
置き換えがひとつもない。
データはすべてajaxによってjson形式でサーバから取得してそのデータに基づいて
表示している。

jsはprototype.js以外は自作のjsファイルだ。
pythonを使う人は比較的jQueryを使う人が多いのだが、私はprototypeの方が
bind関数やquery stringのパース、htmlのエスケープ関数が最初から用意されていて
ありがたい。
document.observe('dom:loaded',function(){}はprototype.jsの常套句で、htmlのdom
が一通りパースされ、すべてのelementに対してイベントが登録できる状態(イメージの
読み込み等はまだ)になったときに呼び出されるイベントハンドラである。
accountData = new AccountList('accountTable',"day","account");
は AccountList(一覧を表示するdivのID,一覧の種類,jsonを取得する際に渡すデータの
元となるformのID)のオブジェクト呼び出しである。
一覧の種類は今のところ"day"と"list"があり、メインページで使用する"day"は当日
使った費用の一覧で、日付は自明のため出力せず、データを削除するためのボタン
は出力する。
一覧画面で出す"list"は日付はまたがるため出力し、削除ボタンは出力しないという
違いがある。
dateSelector = new DateSelector('account','account_date',setAccountData);は
DateSelector(jsonを取得する際に渡すデータの元となるformのID,日付選択のselectを
作成するdivのID,日付が変わった際に呼び出すコールバック関数)のオブジェクトを
作成している。
setCategories()はajaxで項目一覧(食費や交通費)のjsonを取得し、ID items_span
のdivの中に項目を選択できるselectを作成している。

各jsは明日以降説明する。

|

« google app engineで家計簿作り | トップページ | google app engineで家計簿3 »

Google App Engine」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/68673/43106830

この記事へのトラックバック一覧です: google app engineで家計簿作り2:

« google app engineで家計簿作り | トップページ | google app engineで家計簿3 »