自宅サーバーでのオンライン家計簿の公開あきらめました。

やっぱり、自宅サーバーからの公開は無理がありました。
ということで、自宅サーバー完全撤退です。

無料オンライン家計簿MinkはGoogle Apps阪を開発します。
残念。

FaceBook始めました。

けっこういろんなことができるようで、なかなか難しい。
自分の会社の人達も結構FaceBookユーザーが多い。
なんか、面白そう。

iPhone用家計簿Javascriptのコード

きれいなソースではありませんが、何かの参考になれば。
ポイントは、iPhone内のデータベースのInsertやSelect,Updateなどは、非同期で実行される点。
functionの最後にSelectした結果をreturnしてもreturnされないこともあります。


var initflag=0;//初期化完了フラグ
//var jQT;
var db=null;
var datalist="";//SELECTの結果
var flag=0;//0 UPDATE 1 DELETE
var sdat;//集計期間 開始日
var edat;//集計期間 終了日
var tdat;//今日
var kid;//仕分けデータID
var cnt=0,cnt2=0,cardkin=0;//cnt 今日の入力件数 cnt2 期間中の件数
var inkin="収入計:"+0+"円";
var outkin="支出計:"+0+"円";
var syushi="収 支:"+0+"円";//収支計 
var usecard=0;//クレジットカード 初期値 使わない
var usebank=0;//銀行口座 初期値 使わない
var soutkamokumei = new Array("未使用","食費","外食","日用雑貨","衣料費","嗜好品","医療費","交通費・ガソリン代","教育・教養","娯楽・レジャー","慶弔・交際費","雑費","電気","ガス","水道","電話・携帯・インターネット","住居費","保険料","定期預金","ローン引落し","クレジット引落し","新聞・受信料","税金");
var sinkamokumei = new Array("未使用","現金払い","カード払い","口座引落");
var hdat,hkingaku,hbikou,haraiid,hkamokuid;
function nullDataHandler(tx, rs) {
}
function TransactionErrorCallback(error){
    alert('Oops.  Error was '+error.message+' (Code '+error.code+')');
}

function errorHandler(transaction, error){//エラーハンドラ
    alert('エラー Error was '+error.message+' (Code '+error.code+')');
    var we_think_this_error_is_fatal = true;
    if (we_think_this_error_is_fatal) return true;
    return false;
}
function createDB(){//データベースの構築
try {
    if (!window.openDatabase) {
        alert('このサイトはSafariでご利用ください。\niPhoneおよびWindows阪Mac阪Safariでご利用いただけます。');
    } else {
    var shortName = 'minkdb';
    var version = '1.0';
    var displayName = '家計簿Minkデータベース';
    var maxSize = 5000000; // in bytes
        db = openDatabase(shortName, version, displayName, maxSize);
    }
} catch(e) {
    // Error handling code goes here.
    if (e == 2) {
        // Version number mismatch.
        alert("データベースバージョン不一致エラー");
    } else {
        alert("不明なエラー"+e+".");
    }
    return;
}
var dat= new Date();
var m=(dat.getMonth()+1);
var d=dat.getDate();
if((dat.getMonth()+1)<10){
m="0"+(dat.getMonth()+1);
}
if(dat.getDate()<10){
d="0"+dat.getDate();
}
tdat = dat.getFullYear()+"/"+m+"/"+d;
//droptable();//データの削除
db.transaction(function(tx) {// テーブルを作る
tx.executeSql('CREATE TABLE IF NOT EXISTS user (sdate TEXT,edate TEXT,card INTEGER,bank INTEGER);', [], nullDataHandler, errorHandler);
tx.executeSql('SELECT * FROM user;', [], function (tx, resultSet) {
    if(resultSet.rows.length==0){//userが存在しない場合
    var dat= new Date();
    var m=(dat.getMonth()+1);
    var d=dat.getDate();
    if((dat.getMonth()+1)<10){
    m="0"+(dat.getMonth()+1);
    }
    if(dat.getDate()<10){
    d="0"+dat.getDate();
    }
    var today = dat.getFullYear()+"/"+m+"/"+d;
    var dat2=computeDate(dat.getFullYear(),dat.getMonth()+1,dat.getDate(),30);
    m=(dat2.getMonth()+1);
    d=dat2.getDate();
    if((dat2.getMonth()+1)<10){
    m="0"+(dat2.getMonth()+1);
    }
    if(dat2.getDate()<10){
    d="0"+dat2.getDate();
    }
    var nextmonth=dat2.getFullYear()+"/"+m+"/"+d;
    tx.executeSql('insert into user values(?,?,?,?);', [today,nextmonth,1,0], [], nullDataHandler, errorHandler);
    sdat = today;
    edat = nextmonth;
    usecard = 1;
    usebank = 0;
    }else{
    tx.executeSql('SELECT * FROM user;', [], function (tx, rs){
    var row = rs.rows.item(0);
        sdat = row['sdate'];
        edat = row['edate'];
        usecard = row['card'];
        usebank = row['bank'];
        
    }, errorHandler);
    }

    homeUpdate();
}, errorHandler);
tx.executeSql('CREATE TABLE IF NOT EXISTS shiwake(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, type TEXT,date TEXT,hid INTEGER,kid INTEGER,kingaku INTEGER,bikou TEXT)');
}, TransactionErrorCallback,function(){});
}
function homeUpdate(){
var ink=0;
var outk=0;
var syushik=0;
db.transaction(function(tx) {//
tx.executeSql('SELECT count(*) as cnt FROM shiwake where date=?;', [tdat], function (tx, resultSet) {
var row =resultSet.rows.item(0);
cnt = row.cnt;//今日の入力件数
tx.executeSql('SELECT count(*) as cnt FROM shiwake where date between "'+sdat+'" and "'+ edat+'";', [], function (tx, resultSet) {
var row =resultSet.rows.item(0);
cnt2=row["cnt"];//指定機関の入力件数
tx.executeSql('SELECT sum(kingaku) as kin FROM shiwake where type ="in" and hid = 1 and date between "'+sdat+'" and "'+ edat+'";', [], function (tx, resultSet) {
var row =resultSet.rows.item(0);
ink=row["kin"];
if(ink==null){
inkin="収入計:0円";//収入を集計
}else{
inkin="収入計:"+addFigure(ink)+"円";//収入を集計
}
tx.executeSql('SELECT sum(kingaku) as kin FROM shiwake where type = "out" and hid = 1 and date between "'+sdat+'" and "'+ edat+'";', [], function (tx, resultSet) {
var row =resultSet.rows.item(0);
outk=row["kin"];
if(outk==null){
outkin="支出計:0円";//収入を集計
}else{
outkin="支出計:"+addFigure(outk)+"円";//収入を集計
}
tx.executeSql('SELECT sum(kingaku) as kin FROM shiwake where type = "out" and hid = 2 and date between "'+sdat+'" and "'+ edat+'";', [], function (tx, resultSet) {
var row =resultSet.rows.item(0);
var cardw=row["kin"];
if(cardw==null){
cardkin= "";//カーリ利用額を計算
}else{
cardkin= "カード利用計:"+addFigure(cardw)+"円";//カーリ利用額を計算
}
syushik=ink-outk;
syushi="収 支:"+addFigure(syushik) +"円";//収支;
if(initflag==0){
        $(function(){
        $('#sin')
            .bind('pageAnimationStart', function(e, info){ 
    if(tdat<sdat){
    $(this).find('#sindate').html(getCal(sdat));
    }else{
    $(this).find('#sindate').html(getCal(tdat));
    }
           
            document.forms["sin"].reset();
            })            
            .bind("submit",function(){
        sin();
            });
        $('#sinh')
            .bind('pageAnimationStart', function(e, info){ 
            //hensyu();
            document.forms["sinh"].reset();
            })
        .bind('pageAnimationEnd', function(e, info){ 
        $(this).find('#sinhdate').html(getCal(hdat));
            $("#sinhkingaku").val(hkingaku);
            $("#sinhbikou").val(hbikou);
        });
        $('#south')
            .bind('pageAnimationStart', function(e, info){ 
            //hensyu();
            document.forms["south"].reset();
            })
            .bind('pageAnimationEnd', function(e, info){ 
            $(this).find('#southdate').html(getCal(hdat));
            $(this).find('#southkamoku').html(getsoutKamoku());
            $(this).find('#southshiharai').html(getHarai());
            $("#southkingaku").val(hkingaku);
            $("#southbikou").val(hbikou);
            });
            $('#sout')

            .bind('pageAnimationStart', function(e, info){
            if(tdat<sdat){
            $(this).find('#soutdate').html(getCal(sdat));
    }else{
    $(this).find('#soutdate').html(getCal(tdat));
    }
$(this).find('#soutkamoku').html(getsoutKamoku());
$(this).find('#soutshiharai').html(getHarai());
document.forms["sout"].reset();
            })
            .bind("submit",function(){
        sout();
            });
            $('#kikanset')
            .bind('pageAnimationStart', function(e, info){ 
            $(this).find('#date1').html(getCal(sdat));
$(this).find('#date2').html(getCal(edat));
            })
           
            .bind("submit",function(){
        setKikan();
            });
            $('#todaydata')
            .bind('pageAnimationEnd', function(e, info){ 
$(this).find('#tdlist').html(datalist);
            })
            .bind('pageAnimationStart', function(e, info){ 
            showdatalist("today");
            $(this).find('#tdate').html(convjpDate(tdat));
            });
            $('#kikandata')
            .bind('pageAnimationEnd', function(e, info){ 
$(this).find('#kdlist').html(datalist);
            })

            .bind('pageAnimationStart', function(e, info){ 
            showdatalist("kikan");
            $(this).find('#ksdate').html(convjpDate(sdat));
$(this).find('#kedate').html(convjpDate(edat));
            });
            $('#kamokudata')
            .bind('pageAnimationEnd', function(e, info){ 
$(this).find('#kamokulist').html(datalist);
            })
            .bind('pageAnimationStart', function(e, info){ 
     
            kamokudatalist();
            $(this).find('#ksdate').html(convjpDate(sdat));
$(this).find('#kedate').html(convjpDate(edat));
            });
            $('#home')
                .ready(function(e, info){  
                $(this).find('#copyright').html(getCopyright());
    $(this).find('#sdate').text(convjpDate(sdat));
$(this).find('#edate').text(convjpDate(edat));
$(this).find('#todaycnt').text(cnt);
$(this).find('#kikancnt').text(cnt2);
$(this).find('#insum').text(inkin);
$(this).find('#outsum').text(outkin);
$(this).find('#syushi').text(syushi);
$(this).find('#cardkei').text(cardkin);
                })
                .bind('pageAnimationStart', function(e, info){
                homeUpdate();
                })
.bind('pageAnimationEnd', function(e, info){ 
$(this).find('#sdate').text(convjpDate(sdat));
$(this).find('#edate').text(convjpDate(edat));
$(this).find('#todaycnt').text(cnt);
$(this).find('#kikancnt').text(cnt2);
$(this).find('#insum').text(inkin);
$(this).find('#outsum').text(outkin);
$(this).find('#syushi').text(syushi);
$(this).find('#cardkei').text(cardkin);
          });
           
        });
        initflag=1;//初期化完了
       
}else{
//jQT.goTo($('#home'), 'cube');
}
});
}, errorHandler);
}, errorHandler);
}, errorHandler);
}, errorHandler);
}, TransactionErrorCallback);
}
function getCal(setdate){//前後1年間の日付を表示
var now = new Date();
var hi;
if(setdate==null){
hi=now;
}else{
hi = new Date(setdate);
}
var selectdata="";
var m,d;
for(var i=-365;i<0;i++){
var dat=computeDate(now.getFullYear(),now.getMonth()+1,now.getDate(),i);
m=(dat.getMonth()+1);
d=dat.getDate();
if((dat.getMonth()+1)<10){
m="0"+(dat.getMonth()+1);
}
if(dat.getDate()<10){
d="0"+dat.getDate();
}
if((dat.getFullYear()+"/"+dat.getMonth()+"/"+dat.getDate())==(hi.getFullYear()+"/"+hi.getMonth()+"/"+hi.getDate())){
selectdata+='<option value="'+dat.getFullYear()+"/"+m+"/"+d+'" selected>'+dat.getFullYear()+"年"+(dat.getMonth()+1)+"月"+dat.getDate()+'日'+getYoubi(dat.getDay())+'</option>';
}else{
selectdata+='<option value="'+dat.getFullYear()+"/"+m+"/"+d+'">'+dat.getFullYear()+"年"+(dat.getMonth()+1)+"月"+dat.getDate()+'日'+getYoubi(dat.getDay())+'</option>';
}
}
var dat=computeDate(now.getFullYear(),now.getMonth()+1,now.getDate(),0);
m=(dat.getMonth()+1);
d=dat.getDate();
if((dat.getMonth()+1)<10){
m="0"+(dat.getMonth()+1);
}
if(dat.getDate()<10){
d="0"+dat.getDate();
}
if((dat.getFullYear()+"/"+dat.getMonth()+"/"+dat.getDate())==(hi.getFullYear()+"/"+hi.getMonth()+"/"+hi.getDate())){
selectdata+='<option value="'+dat.getFullYear()+"/"+m+"/"+d+'" selected>'+dat.getFullYear()+"年"+(dat.getMonth()+1)+"月"+dat.getDate()+'日'+getYoubi(dat.getDay())+'</option>';
}else{
selectdata+='<option value="'+dat.getFullYear()+"/"+m+"/"+d+'">'+dat.getFullYear()+"年"+(dat.getMonth()+1)+"月"+dat.getDate()+'日'+getYoubi(dat.getDay())+'</option>';
}
for(var i=1;i<365;i++){
var dat=computeDate(now.getFullYear(),now.getMonth()+1,now.getDate(),i);
m=(dat.getMonth()+1);
d=dat.getDate();
if((dat.getMonth()+1)<10){
m="0"+(dat.getMonth()+1);
}
if(dat.getDate()<10){
d="0"+dat.getDate();
}
if((dat.getFullYear()+"/"+dat.getMonth()+"/"+dat.getDate())==(hi.getFullYear()+"/"+hi.getMonth()+"/"+hi.getDate())){
selectdata+='<option value="'+dat.getFullYear()+"/"+m+"/"+d+'" selected>'+dat.getFullYear()+"年"+(dat.getMonth()+1)+"月"+dat.getDate()+'日'+getYoubi(dat.getDay())+'</option>';
}else{
selectdata+='<option value="'+dat.getFullYear()+"/"+m+"/"+d+'">'+dat.getFullYear()+"年"+(dat.getMonth()+1)+"月"+dat.getDate()+'日'+getYoubi(dat.getDay())+'</option>';
}
}
return selectdata;
}
//n日後、n日前の日付を求める
/* 年月日と加算日からn日後、n日前を求める関数 year 年 month 月* day 日 addDays 加算日。マイナス指定でn日前も設定可能
 */
function computeDate(year, month, day, addDays) {//日付の計算
    var dt = new Date(year, month - 1, day);
    var baseSec = dt.getTime();
    var addSec = addDays * 86400000;//日数 * 1日のミリ秒数
    var targetSec = baseSec + addSec;
    dt.setTime(targetSec);
    return dt;
}
function getYoubi(day){//曜日の取得
var youbi="";
switch(day){
case 0:
youbi="(日)";break;
case 1:
youbi="(月)";break;
case 2:
youbi="(火)";break;
case 3:
youbi="(水)";break;
case 4:
youbi="(木)";break;
case 5:
youbi="(金)";break;
case 6:
youbi="(土)";break;
}
return youbi;
}
function convjpDate(date){//yyyy年mm月dd日(Y)形式に変換
var ret="";
var dat= new Date(date);
ret +=dat.getFullYear()+"年"+(dat.getMonth()+1)+"月"+dat.getDate()+'日'+getYoubi(dat.getDay());
return ret;
}
function getsoutKamoku(){//支出科目を表示
var selectsoutkamoku="";
//alert(hkamokuid);
for(var i=1;i<soutkamokumei.length;i++){
if(hkamokuid==i){
selectsoutkamoku+='<option value="'+i+'"selected>'+soutkamokumei[i]+'</option>';
}else{
selectsoutkamoku+='<option value="'+i+'">'+soutkamokumei[i]+'</option>';
}
}
return selectsoutkamoku;
}
function getHarai(){//支払い方法を表示
var southarai="";
if(haraiid==1){
southarai+='<option value="1" selected>現金払い</option>';
}else{
southarai+='<option value="1">現金払い</option>';
}
if(usecard=="1"){
if(haraiid==2){
southarai+='<option value="2" selected >クレジットカード払い</option>';
}else{
southarai+='<option value="2">クレジットカード払い</option>';
}
}
if(usebank=="1"){
if(haraiid==3){
southarai+='<option value="3" selected >口座引き落とし</option>';
}else{
southarai+='<option value="3">口座引き落とし</option>';
}
}
return southarai;
}
function getCopyright(){
var txt=
'<p>Copyright 2010-2011 <a href="http://www.tklab.info/">Tklab.info</a></P>';
return txt;
}
function setKikan(){//期間設定
sdat = document.forms["setKikan"].elements["date1"].value;
edat = document.forms["setKikan"].elements["date2"].value;
if(sdat>edat){
var work=sdat;
sdat=edat;
edat=work;
}
db.transaction(function(tx) {
tx.executeSql('update user set sdate=?,edate=?;', [sdat,edat], nullDataHandler, errorHandler);
},errorHandler,function(){
alert("集計期間を設定しました。");
jQT.goBack("#home","cube");
});
}
function sin(){//収入入力
var sdat = document.forms["sin"].elements["sindate"].value;
var kingaku = document.forms["sin"].elements["kingaku"].value;
var bikou =document.forms["sin"].elements["bikou"].value;
if(isNaN(kingaku) || kingaku==""){
alert("金額が入力されていません。");
return;
}
db.transaction(function(tx) {
tx.executeSql('insert into shiwake (type,date,hid,kid,kingaku,bikou) values (?,?,?,?,?,?);', ["in",sdat,1,1,kingaku,bikou], 
function(){
jQT.goBack("home","cube");
}, errorHandler);
});
}
function sout(){//支出入力
var sdat = document.forms["sout"].elements["soutdate"].value;
var kingaku = document.forms["sout"].elements["kingaku"].value;
var bikou =document.forms["sout"].elements["bikou"].value;
var harai = document.forms["sout"].elements["soutshiharai"].value;
var kamoku =document.forms["sout"].elements["soutkamoku"].value;
if(isNaN(kingaku) || kingaku==""){
alert("金額が入力されていません。");
return;
}
db.transaction(function(tx) {
tx.executeSql('insert into shiwake (type,date,hid,kid,kingaku,bikou) values (?,?,?,?,?,?);', ["out",sdat,harai,kamoku,kingaku,bikou], 
function(){
jQT.goBack("home","cube");
}, errorHandler);
});
}
function addFigure(str) {//3桁区切りカンマを追加
var num = new String(str).replace(/,/g, "");
while(num != (num = num.replace(/^(-?\d+)(\d{3})/, "$1,$2")));
return num;
}
function showdatalist(flag){//期間中のリストを表示
var sql="";
if(flag=="kikan"){
sql='SELECT * FROM shiwake where date between "'+sdat+'" and "'+ edat+'"order by date desc;';
}else if(flag=="today"){
sql='SELECT * FROM shiwake where date ="'+tdat+'"order by id desc;';
}
datalist="";
db.transaction(function(tx) {// テーブルを取得
tx.executeSql(sql, [], function (tx, resultSet) {
for(var i=0;i<resultSet.rows.length;i++){
var row =resultSet.rows.item(i);
datalist+='<LI><form method="POST"name="hensyu'+row.id+'">';
if(row.type=="in"){
datalist+='<a href="#sinh" onTouchend="formCheck(this);"onclick="formCheck(this);">';
}else if(row.type=="out"){
datalist+='<a href="#south"onTouchend="formCheck(this);" onclick="formCheck(this);">';
}
if(flag=="kikan"){
datalist+=convjpDate(row.date)+"<BR>";
}
if(row.type=="in"){
datalist+="収入";
}else if(row.type=="out"){
datalist+=soutkamokumei[row["kid"]];
}
datalist+=" "+addFigure(row["kingaku"])+"円";
if(row.type=="out"){
datalist+=" "+sinkamokumei[row["hid"]];
}
datalist+="<BR>"+row["bikou"];
datalist+='<input type="hidden" id="kid"name="kid" value="'+row.id+'">';
datalist+="</a></form></LI>";
}
if(flag=="kikan"){
if(cnt2==0){
datalist="<li>期間中のデータはありません。</li>";
}
//jQT.goTo("#kikandata","cube");
}else if(flag=="today"){
if(cnt==0){
datalist="<li>今日のデータはありません。</li>";
}
//jQT.goTo("#todaydata","cube");
}
}, function(){
});
},errorHandler,function(){});
}
function kamokudatalist(){//科目別リストを表示
var sql='SELECT kid,sum(kingaku) as kin  FROM shiwake where type = "out" and date between "'+sdat+'" and "'+ edat+'" and hid=1 group by kid order by kid ;';
datalist="";
db.transaction(function(tx) {// テーブルを取得
tx.executeSql(sql, [], function (tx, resultSet) {
var cntx=0;
for(var i=0;i<resultSet.rows.length;i++){
var row =resultSet.rows.item(i);
if(row["kin"]!=0){
datalist+='<LI>'+soutkamokumei[row["kid"]]+" "+addFigure(row["kin"])+"円</LI>";
cntx++;
}
}
if(cntx==0){
datalist="<li>期間中のデータはありません。</li>";
}
}, function(){});
},errorHandler,function(){});
}
function formCheck(obj){ //クリックされたidを格納
var nam = obj.parentElement.name; 
kid = document.forms(nam).kid.value; 
hensyu();
}
function hensyu(){//編集画面へデータ代入
db.transaction(function(tx) {// テーブルを作る
tx.executeSql('SELECT * FROM shiwake where id =?;', [kid], function (tx, resultSet) {
for(var i=0;i<resultSet.rows.length;i++){
var row =resultSet.rows.item(i);
hdat=row.date;
hkingaku=row.kingaku;
hbikou=row.bikou;
haraiid=row.hid;
hkamokuid=row.kid;
hmode=row.type;
}
}, errorHandler);
},errorHandler,function(){});
function sdelete(){//テーブルの削除
if(window.confirm('このデータを削除します。')){
db.transaction(function(tx) {
tx.executeSql('delete from shiwake where id=?;', [kid], nullDataHandler, errorHandler);
},errorHandler,function(){ 
alert("削除しました。");
jQT.goBack("#home","cube");
});
}
}
function supdate(){//テーブルの削除
if(window.confirm('このデータを変更します。')){
if(hmode=="out"){
hdat=document.forms["south"].elements["southdate"].value;
hkingaku=document.forms["south"].elements["kingaku"].value;
hbikou=document.forms["south"].elements["bikou"].value;
haraiid=document.forms["south"].elements["southshiharai"].value;
hkamokuid=document.forms["south"].elements["southkamoku"].value;
}else if(hmode=="in"){
hdat=document.forms["sinh"].elements["sinhdate"].value;
hkingaku=document.forms["sinh"].elements["kingaku"].value;
hbikou=document.forms["sinh"].elements["bikou"].value;
//haraiid=document.forms["sinh"].elements["sinhshiharai"].value;
//hkamokuid=document.forms["sinh"].elements["sinhkamoku"].value;
}
db.transaction(function(tx) {
tx.executeSql('update shiwake set date =?,kingaku=?,bikou=?,hid=?,kid=?,type=? where id=?;', [hdat,hkingaku,hbikou,haraiid,hkamokuid,hmode,kid], nullDataHandler, errorHandler);
},errorHandler,function(){ 
alert("更新しました。");
jQT.goBack("#home","cube");
});
}
}