Ajaxの非同期通信を使ったPOSTメソッドによるHTTP通信を実現する。
今更な感があるが、jQueryなどのライブラリを利用する機会が多くなったため、
少しレイヤを下げて、改めて、JavaScriptとDOM(Document Object Model)の
コードを組み合わせた簡易なWEBアプリケーションを構築したくなったしだい。
◆ 動作概要
クライアントが入力フォーム(nameとage)を入力しsendボタンを押すと、
サーバへ非同期にPOST通信を発生させる。
サーバ側がフォームの内容をCGIで処理して実行結果をクライアントへ返答。
サーバからの応答はHTMLコード下段の部分に挿入する。
ページが遷移しないところがポイントである。
◆ HTMLコード
※サーバ設定がないため(CGIが実行できないので)、動作はしない
POST TEST
samplesend form
returning data
name: -
age: -
(実HTML)
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<title>POST TEST</title>
<link href="post.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="post.js"></script>
</head>
<body>
<h1>POST TEST</h1>
<p>sample</p>
<hr />
<h2>send form</h2>
<form action="post.rb" id="sendForm">
<div>
name:
<input type="text" id="name" name="name" size="30" autocomplete="off" />
</div>
<div>
age:
<input type="text" id="age" name="age" size="3" autocomplete="off" />
</div>
<div>
<input type="button" name="sendBtn" id="sendBtn" value=“send” />
<div>
</form>
<hr />
<h2>returning data</h2>
<div>name: <span id="responseName">-</span></div>
<div>age: <span id="responseAge">-</span></div>
</body>
</html>
◆ CGIコード
#!/usr/bin/ruby
require "cgi"
cgi = CGI.new
name = cgi["name"]
age = cgi['age']
response = "name\t#{name}\n"
response += "age\t#{age}\n"
puts cgi.header
#puts "Content-Type: text/plain; charset=utf-8";
print "\n"
print response
◆ JavaScriptコード
簡単なコードなので説明は省略。
一部利用しない関数を断りを入れて書いているが、
これはただの自分用メモである。
var httpObj;
var timerId;
var timeoutSec = 10;
function printResData(textData) {
var i;
var lines = textData.split("¥n");
var responseName = document.getElementById('responseName');
var responseAge = document.getElementById('responseAge');
for(i = 0; i < lines.length; i ++) {
var parts = lines[i].split("¥t");
var name = parts[0];
var value = parts[1];
if(name == 'name') {
responseName.childNodes[0].nodeValue = value;
} else if(name == 'age') {
responseAge.childNodes[0].nodeValue = value;
}
}
document.getElementById('sendBtn').disabled = false;
}
function postData(e) {
document.getElementById('sendBtn').disabled = true;
var name = document.getElementById('name').value;
var age = document.getElementById('age').value;
var postData;
postData = 'name=' + encodeURIComponent(name) +
'&age=' + encodeURIComponent(age);
var targetUrl = 'post.rb';
httpPostRequest(targetUrl, postData, printResData);
}
function httpPostRequest(targetUrl, postData, funcitonReference) {
try {
if(window.XMLHttpRequest) {
httpObj = new XMLHttpRequest();
} else {
httpObj = false;
}
} catch(e) {
httpObj = false;
}
if(! httpObj) {
fail();
}
timerId = setInterval('timeoutCheck()', 1000);
httpObj.open("POST", targetUrl, true);
httpObj.onreadystatechange = function() {
if (httpObj.readyState == 4) {
clearInterval(timerId);
if (httpObj.status == 200) {
funcitonReference(httpObj.responseText);
} else {
alert(httpObj.status + ' : ' + httpObj.statusText);
return false;
}
}
}
httpObj.send(postData);
}
function fail() {
alert("error: your browser is not supported");
return false;
}
function timeoutCheck() {
timeoutSec --;
if(timeoutSec <= 0) {
clearInterval(timerId);
httpObj.abort();
alert('error: timeout');
return false;
}
}
function setListeners(e) {
var sendBtn = document.getElementById('sendBtn');
// true: capturing(from top), false: bubbling(from bottom)
addListener(sendBtn, 'click', postData, false);
}
function addListener(elem, eventType, func, cap) {
if(elem.addEventListener) {
elem.addEventListener(eventType, func, cap);
} else {
fail();
return false;
}
}
/* 以下はここでは使わない
function removeListener(elem, eventType, func, cap) {
elem.removeEventListener(eventType, func, cap);
}
function getElemPos(elem) {
var obj = new Object();
obj.x = elem.offsetLeft;
obj.y = elem.offsetTop;
while(elem.offsetParent) {
elem = elem.offsetParent;
obj.x += elem.offsetLeft;
obj.y += elem.offsetTop;
}
return obj;
}
function getTargetNode(e) {
var targetNode = e.target;
return targetNode;
}
function stopDefaultAction(e) {
e.preventDefault();
}
function stopPropagation(e) {
e.stopPropagation();
}
*/
addListener(window, 'load', setListeners, false);