授業第7回
1、JSPおさらい
trimDirectiveWhitespaces="true"を付けよう!
2、JSPとjQueryの連携(テーブルとデータ、JSPの準備)
今回は量が多いので、public_html/tomcatに、jqshopというディレクトリを作って、まとめて保存しましょう。
ショップ用のテーブル作成(もうある場合は、それを再利用しても良い)
例 jq_items、jq_customers、jq_ordersテーブルの作成、grant
jqshop.sql (これをviで作っておく。psql db名 < jqshop.sql で一気にテーブルを作成)
drop table jq_orders; drop table jq_items; drop table jq_customers; create table jq_items( id varchar(10) not null primary key, name varchar(100) not null, price int not null, stock int not null ); create table jq_customers( id varchar(10) not null primary key, name varchar(20) not null ); create table jq_orders( id serial primary key, order_date timestamp not null default now(), cid varchar(10) references jq_customers(id) not null, iid varchar(10) references jq_items(id) not null, quantity int not null ); grant all on jq_items to tomcat; grant all on jq_customers to tomcat; grant all on jq_orders to tomcat;
データを入力
例 jqshopdata.sql (psql db名< jqshopdata.sql)
insert into jq_items values('i1001','SoftBank d0201',23000,100); insert into jq_items values('i1002','docomo k3030',45000,100); insert into jq_items values('i1003','kddi g5100',32000,100); insert into jq_items values('i1004','apple iPhone',65000,100); insert into jq_items values('i1005','kddi is08',55000,100); insert into jq_customers values('c01','Hanrin'); insert into jq_customers values('c02','Yamada'); insert into jq_customers values('c03','Nakabayashi'); insert into jq_orders(cid,iid,quantity) values('c01','i1003',3); insert into jq_orders(cid,iid,quantity) values('c01','i1005',10); insert into jq_orders(cid,iid,quantity) values('c02','i1004',4); insert into jq_orders(cid,iid,quantity) values('c02','i1001',5); insert into jq_orders(cid,iid,quantity) values('c01','i1001',6); insert into jq_orders(cid,iid,quantity) values('c01','i1005',2);
jq_itemsのデータを表示するJSPを作成。今のところ、index.jspという名前で。xhtmlを出力させる。jqueryをインポートしておく
例 index.jsp (フォームの文字化け防止、日本国内単位の使用、ページ専用のデータソースのセットをしてあります)
<%@ page contentType="application/xhtml+xml; charset=UTF-8" trimDirectiveWhitespaces="true" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql" %> <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <fmt:requestEncoding value="UTF-8"/> <fmt:setLocale value="ja_JP" /> <sql:setDataSource dataSource="jdbc/hanrin"/> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>ktaishop</title> <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8" /> <script type="text/javascript" src="http://code.jquery.com/jquery-1.6.1.min.js"></script> </head> <body> <sql:query var="rs" sql="select * from jq_items" /> <c:forEach items="${rs.rows}" var="i"> ${i.name}:${i.price}<br /> </c:forEach> </body> </html>
3、JSPから受け取ったデータをjQueryで表示する(1)。
JSPで表示させたデータを、jQueryを用いて操作します。
JSPとjQueryを同時に使う場合、「$」文字が原因でエラーが発生するので、jQueryの部分は、必ず別のファイルにしなければなりません。そのファイルを<script>タグでインポートしておくのを忘れない。
受け取ったデータは、テーブル形式で表示します。
データはjQueryのtr:even(偶数行)tr:odd(奇数行)を使って、色分けして見やすくしましょう。
まずjqshop.jsを書いておく
$(function(){ /* 偶数行と奇数行の色分け */ $("tr:even").css({backgroundColor:"#ffd"}); $("tr:odd").css({backgroundColor:"#ff3"}); });
修正後index.jsp
<%@ page contentType="application/xhtml+xml; charset=UTF-8" trimDirectiveWhitespaces="true" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql" %> <fmt:requestEncoding value="UTF-8"/> <fmt:setLocale value="ja_JP" /> <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>ktaishop</title> <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8" /> <script type="text/javascript" src="http://code.jquery.com/jquery-1.6.1.min.js"></script> <script type="text/javascript" src="jqshop.js"></script> </head> <body> <sql:setDataSource dataSource="jdbc/hanrin"/> <sql:query var="rs" sql="select * from jq_items" /> <table border="1"> <tr> <td>商品ID</td><td>商品名</td><td>価格</td><td>在庫数</td> </tr> <c:forEach items="${rs.rows}" var="i"> <tr> <td>${i.id}</td><td>${i.name}</td><td>${i.price}</td><td>${i.stock}</td> </tr> </c:forEach> </table> </body> </html>
これで、偶数行と奇数行とがきれいに色分けされた表が見られます。
4、JSPから受け取ったデータをjQueryで表示する(2)。
注文するユーザーをセレクトボックスで選べるようにしておきます。
「在庫数」の横の列に、注文個数を入力できる「テキストボックス」を配置します。
index.jsp(修正後)
<%@ page contentType="application/xhtml+xml; charset=UTF-8" trimDirectiveWhitespaces="true" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql" %> <fmt:requestEncoding value="UTF-8"/> <fmt:setLocale value="ja_JP" /> <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>ktaishop</title> <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8" /> <script type="text/javascript" src="http://code.jquery.com/jquery-1.6.1.min.js"></script> <script type="text/javascript" src="jqshop.js"></script> </head> <body> <sql:setDataSource dataSource="jdbc/hanrin"/> <sql:query var="rs" sql="select * from jq_items" /> <sql:query var="rs1" sql="select * from jq_customers" /> <form action=""> <fieldset> <legend>注文フォーム</legend> <select name="customser"> <c:forEach var="j" items="${rs1.rows}"> <option value="${j.id}">${j.name}</option> </c:forEach> </select> <label for="customer">注文者を選ぶ</label> <table border="1"> <tr> <td>商品ID</td> <td>商品名</td> <td>価格</td> <td>在庫数</td> <td>注文個数</td> </tr> <c:forEach items="${rs.rows}" var="i"> <tr> <td>${i.id}</td> <td>${i.name}</td> <td>${i.price}</td> <td>${i.stock}</td> <td><input type="text" class="quantity" name="quantity" size="2" value="0" /></td> </tr> </c:forEach> </table> <input type="submit" value="注文する" /> </fieldset> </form> <div id="warn"></div> </body> </html>
入力された値が数字でない場合、警告を出して、値を「0」にしましょう。
数字かどうかは、javascriptのisNaN()関数を使えば判断出来ます。
(jqueryの$("form").submitイベントを使い、全部数字の場合だけ、送信します)
jqshop.js(修正済み)
$(function(){ /* 偶数行と奇数行の色分け */ $("tr:even").css({backgroundColor:"#ffd"}); $("tr:odd").css({backgroundColor:"#ff3"}); /* 送信前チェック submitの使用*/ $("form").submit(function(){ /* クラスセレクタでテキストボックスそのものの配列を得る */ var a=$(".quantity"); /* 数字以外の場合、この変数に1を足してゆく */ var message=0; /* eachで回し、テキストボックスの値を得る。数字以外の文字を0にして、赤で表示*/ $.each(a,function(){ if($(this).val()==="" || isNaN($(this).val())){ message+=1; $(this).css({color:"#f00"}); $(this).val(0); } }); /* もし、messageが0の場合、数字だけなので、trueを返して、送信処理に移る */ if(message==0){ return true; } /* 数字以外が入力されていたら、送信をキャンセル */ $("#warn").html("数字以外の文字があります:"+message+"個見つかりました"); return false; }); });
5、JSPから受け取ったデータをjQueryで表示する(3)。
個数を入れ終わったら、小計をdivの中に表示してみましょう。
$(this)は現在カーソルがある、選択状態のテキストボックスを意味します。何も入力されていない場合と、数字以外の場合は、エラーを表示します。
単価を取得する時、parent()とprev()メソッドを使って、値を取得します。(テキストボックスの親の、前の前のtextを取得)
計算するときは、取得した値をparseIntして、Javascriptで計算出来るようにしてやらなければなりません。
キーボードを上げた時(keyup時)に、価格と数量をかけ算して、下のdivの中に小計金額を表示します。
jqshop.js(修正後)
$(function(){
/* 偶数行と奇数行の色分け */
$("tr:even").css({backgroundColor:"#ffd"});
$("tr:odd").css({backgroundColor:"#ff3"});
/* 送信前チェック*/
$("form").submit(function(){
var a=$(".quantity");
var message=0;
$.each(a,function(){
if($(this).val()==="" || isNaN($(this).val())){
message+=1;
$(this).css({color:"#f00"});
$(this).val(0);
}
});
if(message==0){
return true;
}
$("#warn").html("数字以外の文字があります:"+message+"個見つかりました");
return false;
}); /* 1文字入力されるたびに、数字かどうかチェックする */
$(".quantity").keyup(function(){
var sum=0;
var a=$(".quantity");
$.each(a,function(){
if($(this).val()==="" || isNaN($(this).val())){
$("#warn").html("数字以外の文字があります");
$("#sum").empty();
return false;
}else{
sum+=parseInt($(this).val()) * parseInt($(this).parent().prev().prev().text());
}
$("#sum").html(sum+"円");
});
});
});
6、データベースへの追加
追加する前に、確認画面を表示(JSPで作成)
この機能のためにデータを<input type="hidden">のvalueにセット
index.jsp(修正後)
<%@ page contentType="application/xhtml+xml; charset=UTF-8" trimDirectiveWhitespaces="true" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql" %>
<fmt:requestEncoding value="UTF-8"/>
<fmt:setLocale value="ja_JP" />
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>ktaishop</title>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8" />
<script type="text/javascript" src="http://code.jquery.com/jquery-1.6.1.min.js"></script>
<script type="text/javascript" src="jqshop.js"></script>
</head>
<body>
<sql:setDataSource dataSource="jdbc/hanrin"/>
<sql:query var="rs" sql="select * from jq_items" />
<sql:query var="rs1" sql="select * from jq_customers" />
<form action="confirm.jsp" method="post">
<fieldset>
<legend>注文フォーム</legend>
<select name="customer">
<c:forEach var="j" items="${rs1.rows}">
<option value="${j.id}">${j.name}</option>
</c:forEach>
</select>
<label for="customer">注文者を選ぶ</label>
<table border="1">
<tr>
<td>商品ID</td>
<td>商品名</td>
<td>価格</td>
<td>在庫数</td>
<td>注文個数</td>
</tr>
<c:forEach items="${rs.rows}" var="i">
<tr>
<td>${i.id}</td>
<td>${i.name}</td>
<td>${i.price}</td>
<td>${i.stock}</td>
<td>
<input style="text-align:right" maxlength="2" type="text" class="quantity" name="quantity" size="2" value="0" />
<input type="hidden" name="iid" value="${i.id}" />
<input type="hidden" name="name" value="${i.name}" />
<input type="hidden" name="price" value="${i.price}" />
</td>
</tr>
</c:forEach>
</table>
<input type="submit" value="注文する" />
</fieldset>
</form>
警告:<div id="warn"></div>
小計:<div id="sum"></div>
</body>
</html>
確認画面に、受け取ったデータを表示。
もしも訂正がある場合は、戻って入力をやり直す。<c:set>を使って、<input type="hidden">から来たデータを受け取る。
もう一回、別のページ(注文確定のページ)にデータを渡す必要があるので、さらに<input type="hidden">に値をセット。
confirm.jsp
<%@ page contentType="application/xhtml+xml; charset=UTF-8" trimDirectiveWhitespaces="true" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> <fmt:requestEncoding value="UTF-8"/> <fmt:setLocale value="ja_JP" /> <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>ktaishop</title> <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8" /> </head> <body> <c:set var="pm" value="${param.customer}" /> <c:set var="pm1" value="${paramValues.iid}" /> <c:set var="pm2" value="${paramValues.name}" /> <c:set var="pm3" value="${paramValues.price}" /> <c:set var="pm4" value="${paramValues.quantity}" /> <form action="fix.jsp" method="post"> <fieldset> <legend>注文確認</legend> <table border="1"> <tr> <td>商品ID</td> <td>商品名</td> <td>価格</td> <td>注文個数</td> </tr> <c:forEach items="${pm1}" var="i" varStatus="x"> <tr> <td>${i}<input type="hidden" name="iid" value="${i}" /></td> <td>${pm2[x.index]}<input type="hidden" name="name" value="${pm2[x.index]}" /></td> <td>${pm3[x.index]}<input type="hidden" name="price" value="${pm3[x.index]}" /></td> <td>${pm4[x.index]}<input type="hidden" name="quantity" value="${pm4[x.index]}" /></td> </tr> </c:forEach> <input type="hidden" name="uid" value="${pm}" /> </table> <input type="submit" value="注文を確定する" /> <a href="index.jsp"><input type="button" value="戻る" /></a> </fieldset> </form> </body> </html>
7、データベースへの書き込み
確認が終わったら、insert文を発行し、データベースに反映する。
ちゃんと追加されたかどうか、確認するために、jq_orderテーブルを一覧表示しましょう。
fix.jsp
<%@ page contentType="application/xhtml+xml; charset=UTF-8" trimDirectiveWhitespaces="true" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql" %>
<fmt:requestEncoding value="UTF-8"/>
<fmt:setLocale value="ja_JP" />
<sql:setDataSource dataSource="jdbc/hanrin" />
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>ktaishop</title>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8" />
</head>
<body>
<c:set var="pm1" value="${paramValues.iid}" />
<c:set var="pm4" value="${paramValues.quantity}" />
<c:set var="pm" value="${param.uid}" />
<sql:transaction isolation="serializable">
<c:forEach items="${pm1}" var="i" varStatus="x">
<fmt:parseNumber var="qt" value="${pm4[x.index]}" />
<c:if test="${qt > 0}">
<sql:update sql="insert into jq_orders(cid,iid,quantity) values(?,?,?);">
<sql:param value="${pm}" />
<sql:param value="${i}" />
<sql:param value="${qt}" />
</sql:update>
</c:if>
</c:forEach>
</sql:transaction>
注文を確定しました
<a href="index.jsp"><input type="button" value="戻る" /></a>
<hr />
<sql:query var="rs" sql="select * from jq_orders" />
<c:forEach var="j" items="${rs.rows}">
ID=${j.id}:
order_date=${j.order_date}:
cid=${j.cid}:
iid=${j.iid}:
quantity=${j.quantity}<br />
</c:forEach>
</body>
</html>
問題
public_html/tomcat/jqshop/に上記のようなショップアプリケーションを作ってください。
(出来れば、「ログイン認証」を付けてください。ログインしたユーザーIDなどを、セッション変数に入れて使い回す方法が良いかもしれません)
① 「index.jsp」が最初に表示されるページなので、このページだけは必ず作ってください。後は各自の自由でよいでしょう。
② なお、このアプリケーションは、在庫の処理をしていません。
商品が購入されたら、jq_itemsから、売れただけの個数を引いて下さい。
③ 注文できる一番多い数は、個数以下にするため、セレクトボックスを使うとよいでしょう。
またはjQueryを使って、注文最大数を超えた入力があった場合、警告をだして注文数を0にする方法でも良いです。そこら辺は、自由に作ってください。
④ あと、商品の画像を表示するようにしておいてください。
⑤ また、商品数が多くなる(100件200件になると、とても見にくい)ことも考えられるので、ページング(いくつかのページに分ける)も出来る人はやっておいてください。テーブルが増えることになるでしょうが。
この課題は、重要な課題評価の対象になります。(一応動いたら50点あげます)
それでは、頑張ってください!