以前から気になっていた「Node.js」という
サーバーサイドのJavaScriptを試してます。
今までやって来たHTAも便利は便利なのですが、
厭くまでローカルの仕組み(プライベート)。
WEBの様で、WEBの勉強には今一つということでの「Node.js」です。
HTAよりは、ネットでの関連情報は多く(というか膨大)ヒットします。
HTAだと、このブログでもさえも、関連ワードさえ、何か入れれば検索エンジンでヒットしてしまいますが、
「Node.js」は、記事数が膨大なのでそんなことはありません。ありえない。
(この記事だと「Node.js版 読書履歴管理システム」としても出て来ないかも・・・)
HTAは趣味の範疇ですが、「Node.js」はちゃんと仕事になりえます。(僕には回って来ませんが…)
財団のページもあります。
https://nodejs.org/ja/
で、ネットで一週間ぐらい、あちこち見て歩いて
HTA版 読書履歴管理システムを移植してみました。
フレームワークは、ネットで盛んに喧伝されているEXPRESS
テンプレートエンジンは、EJS、
そしてDBは、得意のACCESSとの接続例(サンプル)がないので、止む無くMySQLにしました。
ちなみにブラウザは、IE11 限定です(Edgeでは上手く表示できないので断念しました。)
インストール(無料)のやり方は、他のサイト(Qiita等)を参考にして
悪戦苦闘しました。(その通りにやっているつもり(思い込み)なのに、うまく行かない等多々あり)
CSSの外部ファイル化も失敗(何んか読めません。で、ejsの中に書きました。)
書籍等のちゃんと体系化された情報をもとにせず、
まあネット検索で、つまみ食い的な理解度で(内容理解せずモノマネでコーディング)、
取りあえず、動くようにと、それで理解学習につなげようということで
一週間の素人で、バグ、非効率、理解不足は否めないものの
じゃあ、僕がそれを発展させてみようという人が現れること(たらいいな)を期待して
以下に掲載したいと思います。ダメな例として
でもこれだけのソースで、そこそこ動くものが出来るのが驚きです。ハイ!
※環境構築は面倒ですが、使い勝手のご意見や、
こうすれば、もっとよくなるよ的な猫煽て的アドバイスは大歓迎します。
(というか、コメント貰ったことほぼないブログですが・・・)
「無駄なことをするな」的、高所からの見下した切り捨てのコメントはご容赦下さい。
■一覧画面
■登録画面
■更新画面
※以下、ソースのHTMLのタグの< > は、全角に変換してペーストしています。
また、インデントの為、半角スペース2文字を全角スペース1文字に変換しています。
※app.useの辺りは、理解せずに(意味分からず)サンプルのモノマネで書いてます。
※バグも含有してます。(念のため、お断り)
※完璧でないとダメという質ではなく、TRY & GO の性格です。
※課題
簡単なエラーチェックしか入っていません。
入力値が、適正でないと簡単に異常終了することもあります。
ただ、console.logを書けば、簡単にトレース出来るので超便利です。
Edge では、画像がでなかったり、幅がずれたりします。
↑直してくれる方がいれば、有難いですが・・・
CSSが上手く効かない部分もあり、見栄えはこれでも随分苦労しました。
■テーブルの作成(CREATE TABLE) ============================
create table BOOKLOG(
ISBN13 varchar(13) NOT NULL,
ISBN10 varchar(10),
BookName varchar(50) NOT NULL,
Author varchar(25),
Publisher varchar(25),
Genre varchar(25),
IssueDate date ,
GetDate date ,
ReadDate date ,
Ownership tinyint(1) ,
Purchase int(11) ,
Library varchar(25),
Overview varchar(255),
Impressions text ,
State varchar(10),
CoverImg varchar(25),
PRIMARY KEY (ISBN13)
);
■app.js ========================================
var createError = require('http-errors');
var express = require('express');
var bodyParser = require('body-parser');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
// var indexRouter = require('./routes/index');
// var usersRouter = require('./routes/users');
//★1 用意したbooklog.jsをロード
var booklogRouter = require('./routes/booklog');
var addbookRouter = require('./routes/addbook');
var updbookRouter = require('./routes/updbook');
var bookinsRouter = require('./routes/bookins');
var bookupdRouter = require('./routes/bookupd');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
// app.use('/', indexRouter);
// app.use('/users', usersRouter);
//★2 booklog.jsが実行されるアドレスを指定する。
app.use('/booklog', booklogRouter);
app.use('/addbook', addbookRouter);
app.use('/updbook', updbookRouter);
app.use('/bookins', bookinsRouter);
app.use('/bookupd', bookupdRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
■routes/booklog.js =================================
//★1 Expressのライブラリをロード
var express = require('express');
//★2 Routerオブジェクトの作成
var router = express.Router();
var mysql = require('mysql');
const connection = mysql.createConnection({
host: 'localhost',
user: 'TestUser',
password: 'TestUserPW',
database: 'testdb'
});
/* GET tell page. */
//★3 GETされた時のルート情報を登録する
router.get('/', function(req, res, next) {
var query = 'SELECT *,DATE_FORMAT(GetDate,"%Y-%m-%d") AS GDATE FROM testdb.booklog ORDER BY GetDate DESC,ReadDate DESC';
connection.query(query, function (err, rows, fields) {
if (err) { console.log('err: ' + err); }
if (rows.length >= 0) {
//★4 テンプレートファイルのレンダリング
res.render('booklog', { books: rows });
} else {
// render not found page
res.status(404).json({"status_code":404, "status_message": "Not found"});
}
});
});
//★5 exportsにrouterを設定
module.exports = router;
■routes/addbook.js =================================
//★1 Expressのライブラリをロード
var express = require('express');
//★2 Routerオブジェクトの作成
var router = express.Router();
/* GET tell page. */
//★3 GETされた時のルート情報を登録する
router.get('/', function(req, res, next) {
var hiduke=new Date();
var today = hiduke.getFullYear() + "-" + ("0"+(hiduke.getMonth() + 1)).slice(-2) + "-" + ("0"+hiduke.getDate()).slice(-2);
//★4 テンプレートファイルのレンダリング
res.render('addbook',{ today: today });
});
//★5 exportsにrouterを設定
module.exports = router;
■routes/bookins.js =================================
//★1 Expressのライブラリをロード
var express = require('express');
//★2 Routerオブジェクトの作成
var router = express.Router();
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
var mysql = require('mysql');
const connection = mysql.createConnection({
host: 'localhost',
user: 'TestUser',
password: 'TestUserPW',
database: 'testdb'
});
//★3 POSTで受け取る(formのmethodがpostなので)
router.post('/', function(req, res) {
res.setHeader('Content-Type', 'text/plain');
// INSERT処理
var query = 'INSERT INTO testdb.booklog VALUES ("';
query += req.body.honban + '","';
query += req.body.amazonno + '","';
query += req.body.honmei + '","';
query += req.body.sakusya + '","';
query += req.body.honya + '","';
query += req.body.bunrui + '",';
if (req.body.hakkoubi == "") {
query += 'NULL,';
} else {
query += '"' + req.body.hakkoubi + '",';
}
if (req.body.iritebi == "") {
query += 'NULL,';
} else {
query += '"' + req.body.iritebi + '",';
}
if (req.body.yondahi == "") {
query += 'NULL,';
} else {
query += '"' + req.body.yondahi + '",';
}
query += req.body.shoyuu + ',';
query += req.body.hondai + ',"';
query += req.body.tosyokan + '","';
query += req.body.gaiyou + '","';
query += req.body.kansou + '","';
query += req.body.jyokyo + '","';
query += req.body.gazoufile + '")';
console.log(query);
connection.query(query, function(err, result){
if (err) { console.log('err: ' + err); }
//★4 トップページにリダイレクト
res.redirect('/booklog');
});
});
//★5 exportsにrouterを設定
module.exports = router;
■views/booklog.ejs =================================
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>読書履歴</title>
<style>
body{
background-color:#8080ff;
background:linear-gradient(to right, #00008b, #8080ff);
"メイリオ";
}
</style>
</head>
<body>
<table border="0" bgcolor="#FFFFFF" align="center" valign="center" width="95%" height="95%">
<tr valign="top">
<td>
<table width="95%" border="0" align="center" valign="center"
cellspacing="2" cellpadding="2" align="left" style="margin:20px 0px;">
<tr>
<td height="1px" width="20%"> </td>
<td height="1px" width="35%"> </td>
<td height="1px" width="20%"> </td>
<td height="1px" width="15%"> </td>
<td height="1px" width="10%"> </td>
</tr>
<tr class="genrestr" bgcolor="#CCCCFF">
<td colspan="3"><b> 読 書 履 歴 管 理</b></td>
<td colspan="2" align="center"><a href="http://localhost:3000/addbook">新規追加</a></td>
</tr>
<tr align=center bgcolor="#CCCCFF">
<td>ISBN-13</td>
<td>書 名</td>
<td>著 者</td>
<td>入手日</td>
<td>状 況</td>
</tr>
<% books.forEach(function(bookItem) { %>
<tr bgcolor=#E0F1FF>
<td align=center><a href="http://localhost:3000/updbook/<%= bookItem.ISBN13 %>">
<%= bookItem.ISBN13 %></a></td>
<td><%= bookItem.BookName %></td>
<td><%= bookItem.Author %></td>
<td align=center><%= bookItem.GDATE %></td>
<td align=center><%= bookItem.State %></td>
</tr>
<% }); %>
</table>
</td>
</tr>
</table>
</body>
</html>
■views/addbook.ejs =================================
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>読書履歴追加</title>
<style>
body{
width :1100px ;
background-color:#00008b;
background:linear-gradient(to right, #00008b, #8080ff);
"メイリオ";
}
.valueCstr{color:"#000077";font-size:12pt;font-style:normal;text-align=center;}
.ministr {color:"#000077";font-size:8pt;font-style:normal;}
.inpstr1 {color:"#000077";font-size:12pt;font-style:normal;text-align=center;width:155px;border:none;"メイリオ"; .inpstr1A {color:"#000077";font-size:12pt;font-style:normal;text-align=left; width:195px;border:none;"メイリオ";ime-mode: inactive;}
.inpstr1R {color:"#000077";font-size:12pt;font-style:normal; width:70px;border:none;"メイリオ";ime-mode: inactive;}
.inpstr1A {color:"#000077";font-size:12pt;font-style:normal;text-align=left; width:195px;border:none;"メイリオ";ime-mode: active;}
.inpstr2 {color:"#000077";font-size:12pt;font-style:normal;text-align=left; width:320px;border:none;"メイリオ";ime-mode: active;}
.inpstr4 {color:"#000077";font-size:12pt;font-style:normal;text-align=left; width:820px;border:none;"HGゴシックM";ime-mode: active;}
.inpbox {color:"#000077";font-size:11pt;font-style:normal;text-align=left; border:none;"HGゴシックM";}
.selbox {color:"#000077";font-size:12pt;font-style:normal;text-align=center;width:80px;border:none;"メイリオ";}
A: {text-decoration: none }
A:link {color:"#000077"}
A:active {color:steelblue}
A:visited {color:"#000077"}
A:hover {color:steelblue}
</style>
<script type="text/javascript">
<!--
// http://www.html5.jp/tag/elements/forms-constraints.html
function check1(elm) {
if (/9784000000000/.test(elm.value)) {
elm.setCustomValidity('その番号は使えません');
} else {
elm.setCustomValidity('');
}
};
function check2(elm) {
if (/4000000000/.test(elm.value)) {
elm.setCustomValidity('その番号は使えません');
} else {
elm.setCustomValidity('');
}
};
// -->
</script>
</head>
<body>
<form name="formA" method="post" action="/bookins">
<input type="button" value="一覧に戻る" onClick="location.href='http://localhost:3000/booklog'" style="width: 8%; padding: 6px;">
<input type="submit" value="登録する" style="width: 8%; padding: 6px;">
<p>
<table border="0" bgcolor="#00008b" align="center" valign="center" width="98%" height="95%>
<tr valign="top">
<td>
<table width="98%" border="2" align="center" valign="center" bordercolor="#00008b"
cellspacing="2" cellpadding="2" align="left" style="margin:20px 0px;" bgcolor="#00008b">
<tr height="15px" bgcolor="#FFFFFF" bordercolor="#00008b">
<td bgcolor="#E8E0FF" width="10%" align="center"><b>ISBN-13<font size="1" color="#FF3366">※</b></font></td>
<td width="25%"> <input id="honban" name="honban" type="text" placeholder="9784000000000" class="inpstr1" required pattern="\d{13}" title="数字13桁" onchange='check1(this);' /></td>
<td bgcolor="#E8E0FF" width="10%" align="center"><a href="https://www.amazon.co.jp/" target="_blank">ISBN-10</a><font size="1" color="#FF3366"></td>
<td width="25%"> <input id="amazonno" name="amazonno" type="text" placeholder="4000000000" class="inpstr1" pattern="\d{10}" title="数字10桁" onchange='check2(this);' />
<span class="error" aria-live="polite"></span></td>
<td bgcolor="#E8E0FF" width="10%" align="center">状 況</td>
<td> <select name="jyokyo" class="selbox">
<option value="未読" selected>未読</option><option value="読書中">読書中</option><option value="読了">読了</option></select></td>
</tr>
<tr height="15px" bgcolor="#FFFFFF">
<td bgcolor="#E8E0FF" align="center">書 名<font size="1" color="#FF3366">※</b></td>
<td colspan="5" align="left"> <input id="honmei" name="honmei" type="text" class="inpstr4" required></td>
</tr>
<tr height="15px" bgcolor="#FFFFFF">
<td bgcolor="#E8E0FF" align="center">著 者</td>
<td colspan="3" align="left"> <input id="sakusya" name="sakusya" type="text" class="inpstr2"></td>
<td bgcolor="#E8E0FF" align="center">ジャンル</td>
<td align="left"> <input id="bunrui" name="bunrui" type="text" class="inpstr1A"></td>
</tr>
<tr height="15px" bgcolor="#FFFFFF">
<td bgcolor="#E8E0FF" align="center">出 版 社</td>
<td colspan="3" align="left"> <input id="honya" name="honya" type="text" class="inpstr2"></td>
<td bgcolor="#DDEEFF" align="center">画 像</td>
<td align="left"> <input id="gazoufile" name="gazoufile" type="text" class="inpstr1"></td>
</tr>
<tr height="15px" bgcolor="#FFFFFF">
<td bgcolor="#EEDDFF" align="center">発 行 日</td>
<td> <input id="hakkoubi" name="hakkoubi" type="date" class="inpstr1" value="<%= today %>" pattern="\d{4}-\d{2}-\d{2}" title="YYYY-MM-DD"></td>
<td bgcolor="#E8E0FF" align="center">入 手 日</td>
<td> <input id="iritebi" name="iritebi" type="date" class="inpstr1" value="<%= today %>" pattern="\d{4}-\d{2}-\d{2}" title="YYYY-MM-DD"></td>
<td bgcolor="#EEDDFF" align="center">読 了 日</td>
<td> <input id="yondahi" name="yondahi" type="date" class="inpstr1" value="<%= today %>" pattern="\d{4}-\d{2}-\d{2}" title="YYYY-MM-DD"></td>
</tr>
<tr height="15px" bgcolor="#FFFFFF">
<td bgcolor="#DFDFFF" align="center">概 要</td>
<td colspan="5" align="left"> <input id="gaiyou" name="gaiyou" type="text" class="inpstr4"></td>
</tr>
<tr bgcolor="#FFFFFF">
<td bgcolor="#DFDFFF" align="center">感 想</td>
<td colspan="5" align="center">
<textarea name="kansou" cols="122" rows="10" class="inpbox"></textarea></td>
</tr>
<tr height="15px" bgcolor="#FFFFFF">
<td bgcolor="#E8E0FF" align="center">所 有</td>
<td> <select name="shoyuu" class="selbox">
<option value="1" selected>購入</option><option value="0">非購入</option></select></td>
<td bgcolor="#EEDDFF" align="center">購入金額</td>
<td align="left"> \ <input id="hondai" name="hondai" type="number" class="inpstr1R" value=0 style="text-align: right;">-</td>
<td bgcolor="#E8E0FF" align="center">図 書 館</td>
<td align="left"> <input id="tosyokan" name="tosyokan" type="text" class="inpstr1A"></td>
</tr>
</table>
</td>
</tr>
<tr>
<td align="right">
<font class="ministr"><font color="#FF3366">※</font><font color="#FFFFFF">の項目は入力必須項目です。</font>
</td>
</tr>
</table>
</form>
</body>
</html>
※更新画面のソースは、Node.js版 読書履歴管理システム② に続く
コメント一覧
オーナー
オーナー
オーナー
オーナー
オーナー
オーナー
オーナー
オーナー
オーナー
最新の画像もっと見る
最近の「Node.js他(Python)」カテゴリーもっと見る
最近の記事
カテゴリー
- VBScript(2)
- Weblog(314)
- お仕事ツール(0)
- Saloon(1122)
- Node.js他(Python)(16)
- HTA(32)
- 決め・分け論(72)
- 映画・ドラマ(37)
- EXCEL VBA(35)
- PL/SQL(10)
- Java(11)
- 詩(自作)(5)
- 詩(塚原将)(298)
- 短歌(200)
- 題詠100首鑑賞(96)
- 題詠100首(109)
- ALIAS SMITH and JONES エピソード(1)
- 題詠100首2010(11)
- 読書(74)
- プロスポーツ(プロ野球、格闘技)(27)
- 日常・育児とか(88)
- 仕事(IT関係)(61)
- とほほ(33)
- 夢(32)
- 勝手にバトン(7)
- 写真(36)
- スタートレック視聴日誌草稿(24)
- 旅行(25)
- 嫌いな言葉(6)
- 好きな言葉(4)
バックナンバー
人気記事