星期五, 6月 16, 2006

AJAX(JSON)備忘記

在上一編"Ajax備忘記"中,使用了Array及JAVA裡的getter,setter概念來存取property.
這在管理上有點不方便,現在把它改成使用JSON來實作.


下面主要包含3個文檔:
news.xml // xml data file
news.js // logical file
news.html // configuration file


<!-----------news.xml-------------->
<?xml version="1.0" ?>
<ROWSET>
<NEWS>
<NEWS_ITEM num="1">
<ID>TEST 1</ID>
<TITLE>TITLE TEST 1</TITLE>
<CONTENT>CONTENT TEST 1</CONTENT>
</NEWS_ITEM>
<NEWS_ITEM num="2">
<ID>TEST 2</ID>
<TITLE>TITLE TEST 2</TITLE>
<CONTENT>CONTENT TEST 2</CONTENT>
</NEWS_ITEM>
</NEWS>
</ROWSET>
<!-----------news.xml-------------->


<!-----------news.js-------------->
var xmlHttp;
var debug_log = "Start mailto:Debug@@@@@@@/n";

function createXMLHttpRequest() {
if (window.ActiveXObject && !window.XMLHttpRequest) {
window.XMLHttpRequest = function() {
var MSXML = ["Msxml2.XMLHTTP.5.0","Msxml2.XMLHTTP.4.0","Msxml2.XMLHTTP.3.0","Msxml2.XMLHTTP","Microsoft.XMLHTTP"];
for (var i = 0; i < MSXML.length; i++) {
try {
return new ActiveXObject(MSXML[i]);
} catch (e) {
debug_log += "#XMLHTTP TYPE:"+MSXML[i]+"#\n";
}
}
return null;
};
}
xmlHttp = new XMLHttpRequest();
}

function startRequest() {
createXMLHttpRequest();
xmlHttp.onreadystatechange = handleStateChange;
xmlHttp.open("GET", xmlUrl, true);
//xmlHttp.setRequestHeader("If-Modified-Since", xmlHttp.lastModified);
xmlHttp.send(null);
}

function handleStateChange() {
if(xmlHttp.readyState != 4){
//var iTimeoutId = setTimeout(function(){Logger("#Loading#\n");}, 3000);
//clearTimeout(iTimeoutId);
}


if(xmlHttp.readyState == 4) {
if(xmlHttp.status == 200) {
loadXmlData();
is_load = true;
} else {
debug_log += "#http status:"+xmlHttp.status+"#\n";
}
ShowContent();
//Logger(debug_log);
} else {
debug_log += "#readyState:"+xmlHttp.readyState+"#\n";

}
}


function isNewsProperty(property){
var oNews = new News();
for(var i in oNews.items){
if(i == property) return true;
}
return false;
}

function loadXmlData(){
var xmlDoc = xmlHttp.responseXML;
var news_allItem = xmlDoc.getElementsByTagName(news_item_tag_name);
debug_log += "#XML TEXT:"+xmlHttp.responseText+"#\n";
for(var i = 0; i < news_allItem.length; i++){
var oNews = new News();
var item_list = news_allItem[i].childNodes;
for(var k = 0; k < item_list.length; k++){
if(isNewsProperty(item_list[k].tagName)){
oNews.items[item_list[k].tagName] = item_list[k].childNodes[0].nodeValue;
}
}
news_item_list.push(oNews);
}
}

function Logger(msg){
if(document.getElementById("log") == null){
var oDiv = document.createElement("div");
//var oAtt = document.createAttribute("id","log");
//oDiv.setAttributeNode(oAtt);
oDiv.setAttribute("id","log");
document.body.appendChild(oDiv);
}
document.getElementById("log").innerHTML += msg;
}

window.onload = function(){
startRequest();
}
<!-----------news.js-------------->


<!-----------news.html-------------->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Parsing XML Responses with the W3C DOM</title>
<script type="text/javascript">
var xmlUrl = "news.xml";
var news_item_tag_name = "NEWS_ITEM";
function News(){
this.items={
'ID' : '',
'TITLE' : '',
'CONTENT' : ''
};
}
var news_item_list = new Array();
var is_load = false;
</script>


<script type="text/javascript">
function getContent(){
var content = "<table border='1'>";
if(news_item_list.length == 0){
content += "<tr><td>No data</td></tr></table>";
return content;
}


content += "<tr><th>ID</th><th>TITLE</th><th>CONTENT</th></tr>"
for(var i = 0; i < news_item_list.length; i++){
content += "<tr>";
content += "<td>" + news_item_list[i].items.ID + "</td>";
content += "<td>" + news_item_list[i].items.TITLE + "</td>";
content += "<td>" + news_item_list[i].items.CONTENT + "</td>";
content += "<tr>";
}
content += "</table>";
return content;
}


function ShowContent(){
if(document.getElementById("content") == null){
var oDiv = document.createElement("div");
oDiv.setAttribute("id","content");
document.body.appendChild(oDiv);
}
document.getElementById("content").innerHTML = getContent();
}
</script>


<script type="text/javascript" src="news.js"></script>


</head>
<body>
</body>
</html>
<!-----------news.html-------------->



<!-------------Explanation 1------------------------>
<script type="text/javascript">
var xmlUrl = "news.xml"; // xml的相對位置, 亦可輸入url的absolute位置.但不能跨Domain,跨Domain需實作proxy
var news_item_tag_name = "NEWS_ITEM"; // 想要截取的tag name
function News(){
this.items={ // 這裡使用了JSON( JavaScript Object Notation)
'ID' : '',
'TITLE' : '',
'CONTENT' : ''
};
}
var news_item_list = new Array(); // 把所有的NEWS ITEM放進ARRAY裡
var is_load = false; // 是否已把XML資料LOAD完,用作PRE Lodding,這裡沒實作

</script>
<!-------------Explanation 1------------------------>


<!-------------Explanation 2------------------------>
var xmlHttp; // XMLHttpRequest的instance放的變量.
var debug_log = "Start Debug@@@@@@@\n"; // 記錄debug message的變量

function createXMLHttpRequest() {
if (window.ActiveXObject && !window.XMLHttpRequest) {
window.XMLHttpRequest = function() {
// 這裡override window的XMLHttpRequest object,後面使用就不用管它是甚麼Browser( ie or firefox )
var MSXML = ["Msxml2.XMLHTTP.5.0","Msxml2.XMLHTTP.4.0","Msxml2.XMLHTTP.3.0","Msxml2.XMLHTTP","Microsoft.XMLHTTP"];
// 為了相容IE6前的所有BROWSER版本, 所以用FOR LOOP去LOOKUP每個版本ActiveXObject的XMLHTTP.當找到就直接RETURN
for (var i = 0; i < MSXML.length; i++) {
try {
return new ActiveXObject(MSXML[i]);
} catch (e) {
debug_log += "#XMLHTTP TYPE:"+MSXML[i]+"#\n";
}
}
return null;
};
}
xmlHttp = new XMLHttpRequest();
// 由於上面已override window裡的XMLHttpRequest object,所以這裡直接使用
}
<!-------------Explanation 2------------------------>



<!-------------Explanation 3------------------------>
function startRequest() {
createXMLHttpRequest();
xmlHttp.onreadystatechange = handleStateChange;
// onreadystatechange為event handler, 所以當readyState 等於 0,1,2,3,4時,便會call handleStateChange()這個function
// readyState = 0 為uninitialized, 1 為loading, 2 為loaded, 3為interactive, 4為complete
xmlHttp.open("GET", xmlUrl, true);
//xmlUrl就會xml的位置, 為了簡單,這裡只使用靜態的xml檔案,
// 最後的true表示現在是異歩, false為同步,
// 如果設定為同步,在下面送出send時就會等待回應結果,
xmlHttp.send(null);
}

function handleStateChange() {
if(xmlHttp.readyState != 4){
//var iTimeoutId = setTimeout(function(){Logger("#Loading#\n");}, 3000);
//clearTimeout(iTimeoutId);
}


if(xmlHttp.readyState == 4) { // 上面己對readState的各種狀態說明了, 這裡當readyState等於4即已把xml載入完成
if(xmlHttp.status == 200) {
// xmlHttp.status為http status, 200為成功,404為not found
loadXmlData();
// call 自建的 loadXmlData() function. 把xml裡的NEWS_ITEM放進news_item_list ARRAY裡
is_load = true;
} else {
debug_log += "#http status:"+xmlHttp.status+"#\n";
}
ShowContent();
// 當所有NEWS_ITEM載入news_item_list, call 自建的ShowContent() function顯示html
//Logger(debug_log);
} else {
debug_log += "#readyState:"+xmlHttp.readyState+"#\n";

}
}
<!-------------Explanation 3------------------------>



<!-------------Explanation 4------------------------>
function isNewsProperty(property){ // 這個function是判斷xml裡的property有沒有對應News裡的items.
var oNews = new News();
for(var i in oNews.items){ // 把所有items裡的properties逐個取出來
if(i == property) return true;
}
return false;
}

function loadXmlData(){
var xmlDoc = xmlHttp.responseXML; // 把xml document給xmlDoc變量
var news_allItem = xmlDoc.getElementsByTagName(news_item_tag_name);
// 此變量news_item_tag_name 為 "NEWS_ITEM", 所以此句LOOKUP所有NEWS_ITEM node.
debug_log += "#XML TEXT:"+xmlHttp.responseText+"#\n";
for(var i = 0; i < news_allItem.length; i++){
var oNews = new News();
var item_list = news_allItem[i].childNodes; // 這裡將所有NEWS_ITEM裡的node放到item_list變量
for(var k = 0; k < item_list.length; k++){
if(isNewsProperty(item_list[k].tagName)){
oNews.items[item_list[k].tagName] = item_list[k].childNodes[0].nodeValue;
}
}

news_item_list.push(oNews);
// Array裡的push function可看作Array為stack, push data在Array的最後
}
}

function Logger(msg){ // Logger用作debug
if(document.getElementById("log") == null){
var oDiv = document.createElement("div"); // 這裡建立div element.
oDiv.setAttribute("id","log");
// 設定div裡id property為"log"
document.body.appendChild(oDiv);
// 把div element加入html 的body裡, body tag 必須先在html裡建立
}
document.getElementById("log").innerHTML += msg;
}

window.onload = function(){
// 當load完整份html,然後呼叫startRequest()去load xml及顯示html content
startRequest();
}
<!-------------Explanation 4------------------------>


<!-------------Explanation 5------------------------>
<script type="text/javascript">
function getContent(){
// 此function可看到html的template,把資料送給ShowContent() function顯示
var content = "<table border='1'>";
if(news_item_list.length == 0){
content += "<tr><td>No data</td></tr></table>";
return content;
}


content += "<tr><th>ID</th><th>TITLE</th><th>CONTENT</th></tr>"
for(var i = 0; i < news_item_list.length; i++){
content += "<tr>";
content += "<td>" + news_item_list[i].items.ID + "</td>";
content += "<td>" + news_item_list[i].items.TITLE + "</td>";
content += "<td>" + news_item_list[i].items.CONTENT + "</td>";
content += "<tr>";
}
content += "</table>";
return content;
}


function ShowContent(){ // 當readState為4時,load完xml後,呼叫此function顯示data
if(document.getElementById("content") == null){
var oDiv = document.createElement("div");
oDiv.setAttribute("id","content");
document.body.appendChild(oDiv);
}
document.getElementById("content").innerHTML = getContent();
}
</script>
<!-------------Explanation 5------------------------>

沒有留言: