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);