﻿/**
 *  Mydget JavaScript Framework (depends on Yahoo UI, Prototype)
 *  (c) 2007 Fullerton TEchnology Co., Ltd.
 *  Author: Andy Chen
 *  Email: andychen@fullerton.com.tw, andy7ps@eland.idv.tw
 *
 *  Mydget is freely distributable, this copy of software must distributed with a license file,
 *  if you have not license file then you are unlicesed to use this software.
 */

if (typeof FWUI=="undefined") {var FWUI={};}
FWUI.util = {}; //static

// classname for window container
FWUI.util.MODULE_CLASSNAME = 'window-container'; //static
// callback檔案暫存容器
var _STORAGEMAP = new Array();
// 分頁頁碼長度
var _PAGERSIZE = 10;
// 內容長度
var _LIMITCOUNT = 0;
// web application context path
var _WEBROOT = "";

/**
 * window 原型
 * 
 * @class BaseWindow
 * @param panelId(String) window 放置 的panel id
 * @param windowId(String) window id
 * @param cssSource(String) css file url
 * @param templateSource(String) template file url
 * @param xmlSource(String) xml file url
 * @param params(String) 除 url 外額外帶入的參數
 */
FWUI.util.BaseWindow = function(panelId, windowId, cssSource, templateSource, xmlSource, params) {
	if (xmlSource) {
		this.init(panelId, windowId, cssSource, templateSource, xmlSource, params);
	}
};
FWUI.util.BaseWindow.prototype = {
	// panel id
	panelId: null,
	// window id
	windowId: null,
	// css file url
	cssSource: null,
	// template file url
	templateSource: null,
	// xml file url
	xmlSource: null,
	// 除 url 外額外帶入的參數
	params: null,
	// extra data
	extraData: null,
	// function name
	funcName: "FWUI.util.BaseWindow",

	/**
	 * @description 將由 ajax 回傳的成功資料，以文字型式存放於_STORAGEMAP中
	 * @method callback
	 * @private
	 * @param o(Object) ajax connection object
	 */
	callback: function(o) {
		_STORAGEMAP[_key] = o.responseText;
	},

	/**
	 * @description 將由 ajax 回傳的成功資料，以 Template 型式存放於_STORAGEMAP中
	 * @method templateCallback
	 * @private
	 * @param o(Object) ajax connection object
	 */
	templateCallback: function(o) {
		_STORAGEMAP[_key] = new Template(o.responseText);
	},

	/**
	 * @description 將由 ajax 回傳的成功資料，以 xml 型式存放於_STORAGEMAP中
	 * @method xmlCallback
	 * @private
	 * @param o(Object) ajax connection object
	 */
	xmlCallback: function(o) {
		var xmlDoc = o.responseXML;
		if (!xmlDoc) xmlDoc = parseXMLString(o.responseText);
		_STORAGEMAP[_key] = xmlDoc;
	},

	/**
	 * @description 由 ajax 回傳的失敗資料
	 * @method callbackFailure
	 * @private
	 * @param o(Object) ajax connection object
	 */
	callbackFailure: function(o) {
		alert("callbackFailure:" + o.responseText);
	},

	/**
	 * @description 執行 window 的組成
	 * @method run
	 * @private
	 */
	run: function() {
		// 將window 所需的 css, template, xml 資料載入
		this.loadFiles();
		// 額外資料載入
		this.extraLoadFiles();
		// 將下載的資料內容重新整理
		var data = this.dataReconstitute(_STORAGEMAP[this.xmlSource]);
		// window設定，如分頁、more
		data = this.windowConfig(_STORAGEMAP[this.xmlSource], data);
		// 組成 window 資料
		this.dataCombine(data);
	},

	/**
	 * @description 檔案下載
	 * @method loadFiles
	 * @public
	 */
	loadFiles: function() {
		// 下載 css File
//		if (this.cssSource && !_STORAGEMAP[this.cssSource]) {
//			_key = this.cssSource; // 透過全域變數將來源設為 _STORAGEMAP 的 key
//			new Ajax.Request(this.cssSource, {method: 'GET', asynchronous: false, onSuccess: this.callback, onFailure: this.callbackFailure});
//		}
		// 下載 template File
		if (this.templateSource && !_STORAGEMAP[this.templateSource]) {
			_key = this.templateSource; // 透過全域變數將來源設為 _STORAGEMAP 的 key
			new Ajax.Request(this.templateSource, {method: 'GET', asynchronous: false, onSuccess: this.templateCallback, onFailure: this.callbackFailure});
		}
		// 下載 xml File
		if (this.xmlSource) {
			_key = this.xmlSource; // 透過全域變數將來源設為 _STORAGEMAP 的 key
			new Ajax.Request(this.xmlSource, {method: 'GET', asynchronous: false, parameters: this.params, onSuccess: this.xmlCallback, onFailure: this.callbackFailure});
		}
	},

	/**
	 * @description 檔案下載
	 * @method extraLoadFiles
	 * @private
	 */
	extraLoadFiles: function() {
		// 自行實作
	},

	/**
	 * @description 資料重新整理 (需自行實作該部分)
	 * @method dataReconstitute
	 * @private
	 * @param xmlDoc(Document) xml document 物件
	 * @return (Object) 重組後的資料
	 */
	dataReconstitute: function(xmlDoc) {
		// 自行實作
		return {}; // 回傳物件
	},

	/**
	 * @description window設定，如分頁、more
	 * @method windowConfig
	 * @private
	 * @param xmlDoc(Document) xml document 物件
	 * @return (Object) 重組後的資料
	 */
	windowConfig: function(xmlDoc, data) {
		// 自行實作
		return data; // 回傳物件
	},

	/**
	 * @description window 內容的組成
	 * @method dataCombine
	 * @private
	 */
	dataCombine: function(data) {
		// 將整理完的資料放入template
		var content = _STORAGEMAP[this.templateSource].evaluate(data);
		// 設定 window 框架
		this.setPanelWindow(this.panelId, this.windowId);
		// 將組好的 window 放入指定的位置
		set_innerHTML(this.windowId, content);
	},

	/**
	 * @description 設定 window 框架
	 * @method setPanelWindow
	 * @private
	 * @param panelId(String) panel id
	 * @param windowId(String) window id
	 */
	setPanelWindow: function(panelId, windowId) {
		// 檢查是否已有該 window 存在
		var obj = document.getElementById(windowId);
		if (obj) {
			obj.innerHTML = "";
		} else {
			// 新增一 window object
			obj = document.createElement('div');
			obj.id = windowId;
			obj.className = FWUI.util.MODULE_CLASSNAME;

			// 在 panel 內放入 window object
			document.getElementById(panelId).appendChild(obj);
		}
	},
	
	/**
	 * @description 設定 params
	 * @method setParams
	 * @public
	 */
	setParams: function(params) {
	    this.params = params;
	},
	
	/**
	 * @description 設定 xmlSource
	 * @method setXmlSource
	 * @public
	 */
	setXmlSource: function(xmlSource) {
	    this.xmlSource = xmlSource;
	},

	/**
	 * @description window 初始化
	 * @method init
	 * @private
	 */
	init: function(panelId, windowId, cssSource, templateSource, xmlSource, params) {
		this.initTarget(panelId, windowId, cssSource, templateSource, xmlSource, params);
		this.run();
	},

	/**
	 * @description 將由外部傳入的資料設給物件內部的變數使用
	 * @method initTarget
	 * @private
	 */
	initTarget: function(panelId, windowId, cssSource, templateSource, xmlSource, params) {
		this.panelId = panelId;
		if (!windowId) windowId = panelId + (new Date()).getTime();
		this.windowId = windowId;
		this.templateSource = templateSource;
		this.cssSource = cssSource;
		this.xmlSource = xmlSource;
		this.params = params;
	},

	/**
	 * @description 傳回 window id
	 * @method toString
	 * @private
	 * @return (String)
	 */
  toString: function() {
      return (this.funcName + ":" + this.windowId);
  }
};





/**
 * base highlight window
 * 
 * @class BaseHighlight
 * @param panelId(String) window 放置 的panel id
 * @param windowId(String) window id
 * @param cssSource(String) css file url
 * @param templateSource(String) template file url
 * @param xmlSource(String) xml file url
 * @param params(String) 除 url 外額外帶入的參數
 */
FWUI.util.BaseHighlight = function(panelId, windowId, cssSource, templateSource, xmlSource, params) {
	if (xmlSource) {
		this.init(panelId, windowId, cssSource, templateSource, xmlSource, params);
	}
};
// 繼承 base window
FWUI.util.BaseHighlight.prototype = new FWUI.util.BaseWindow;
// override windowConfig
FWUI.util.BaseHighlight.prototype.windowConfig = function(xmlDoc, data) {
	data.pager = FWUI.util.getMoreData(xmlDoc);
	return data;
};





/**
 * base list window
 * 
 * @class BaseList
 * @param panelId(String) window 放置 的panel id
 * @param windowId(String) window id
 * @param cssSource(String) css file url
 * @param templateSource(String) template file url
 * @param xmlSource(String) xml file url
 * @param params(String) 除 url 外額外帶入的參數
 */
FWUI.util.BaseList = function(panelId, windowId, cssSource, templateSource, xmlSource, params) {
	this.funcName = "FWUI.util.BaseList";
	if (xmlSource) {
		this.init(panelId, windowId, cssSource, templateSource, xmlSource, params);
	}
};
// 繼承 base window
FWUI.util.BaseList.prototype = new FWUI.util.BaseWindow;
// override windowConfig
FWUI.util.BaseList.prototype.windowConfig = function(xmlDoc, data) {
	var pager = xmlDoc.getElementsByTagName('pager')[0];
	data.pager = FWUI.util.getPagerData(pager, this.funcName, this.panelId, this.windowId, this.cssSource, this.templateSource, this.xmlSource, this.params);
	return data;
};





/**
 * html window
 * 
 * @class HtmlWindow
 * @param panelId(String) window 放置 的panel id
 * @param windowId(String) window id
 * @param cssSource(String) css file url
 * @param templateSource(String) template file url
 * @param xmlSource(String) xml file url
 * @param params(String) 除 url 外額外帶入的參數
 */
FWUI.util.HtmlWindow = function(panelId, windowId, cssSource, templateSource, xmlSource, params) {
	if (xmlSource) {
		this.init(panelId, windowId, cssSource, templateSource, xmlSource, params);
	}
};
// 繼承 base window
FWUI.util.HtmlWindow.prototype = new FWUI.util.BaseWindow;
// override dataReconstitute
FWUI.util.HtmlWindow.prototype.dataReconstitute = function(xmlDoc) {
	return FWUI.util.getHtmlData(xmlDoc, this.windowId);
};





/**
 * highlight window
 * 
 * @class HighlightWindow
 * @param panelId(String) window 放置 的panel id
 * @param windowId(String) window id
 * @param cssSource(String) css file url
 * @param templateSource(String) template file url
 * @param xmlSource(String) xml file url
 * @param params(String) 除 url 外額外帶入的參數
 */
FWUI.util.HighlightWindow = function(panelId, windowId, cssSource, templateSource, xmlSource, params) {
	if (xmlSource) {
		this.init(panelId, windowId, cssSource, templateSource, xmlSource, params);
	}
};
// 繼承 base window
FWUI.util.HighlightWindow.prototype = new FWUI.util.BaseHighlight;
// override dataReconstitute
FWUI.util.HighlightWindow.prototype.dataReconstitute = function(xmlDoc) {
	// 取得 HTML 資料
	var data = FWUI.util.getHtmlData(xmlDoc, this.windowId);
	// list data
	var listing = FWUI.util.getItemsData(xmlDoc.getElementsByTagName('items')[0], xmlDoc.getElementsByTagName('pager')[0]);
	data.listing = listing;
	return data;
};





/**
 * list window
 * 
 * @class ListWindow
 * @param panelId(String) window 放置 的panel id
 * @param windowId(String) window id
 * @param cssSource(String) css file url
 * @param templateSource(String) template file url
 * @param xmlSource(String) xml file url
 * @param params(String) 除 url 外額外帶入的參數
 */
FWUI.util.ListWindow = function(panelId, windowId, cssSource, templateSource, xmlSource, params) {
	this.funcName = "FWUI.util.ListWindow";
	if (xmlSource) {
		this.init(panelId, windowId, cssSource, templateSource, xmlSource, params);
	}
};
// 繼承 base window
FWUI.util.ListWindow.prototype = new FWUI.util.BaseList;
// override dataReconstitute
FWUI.util.ListWindow.prototype.dataReconstitute = function(xmlDoc) {
	// 取得 HTML 資料
	var data = FWUI.util.getHtmlData(xmlDoc, this.windowId);
	// list data
	var listing = FWUI.util.getItemsData(xmlDoc.getElementsByTagName('items')[0], xmlDoc.getElementsByTagName('pager')[0]);
	data.listing = listing;
	return data;
};





// 取得 xml 裡的 html data
FWUI.util.getHtmlData = function(xmlDoc, windowId, data) {
	if (!data) {
		data = {};
	}
	var type = xmlDoc.getElementsByTagName('window')[0].attributes[0].nodeValue;
	var title = "";
	if (xmlDoc.getElementsByTagName('title')[0]) {
		title = xmlDoc.getElementsByTagName('title')[0].childNodes[0].nodeValue;
	}
	var header = "";
	if (xmlDoc.getElementsByTagName('header')[0]) {
		header = xmlDoc.getElementsByTagName('header')[0].childNodes[0].nodeValue;
	}
	var content = "";
	if (xmlDoc.getElementsByTagName('content')[0] && xmlDoc.getElementsByTagName('content')[0].childNodes[0]) {
		content = xmlDoc.getElementsByTagName('content')[0].childNodes[0].nodeValue;
	}
	var footer = "";
	if (xmlDoc.getElementsByTagName('footer')[0]) {
		footer = xmlDoc.getElementsByTagName('footer')[0].childNodes[0].nodeValue;
	}

	data.id = windowId;
	data.type = type;
	data.title = title;
	data.header = header;
	data.content = content;
	data.footer = footer;

	return data;
};


// 取得 xml 裡的 more data
FWUI.util.getMoreData = function(xmlDoc) {
	// 組成 more 的內容
	var listLink = "";
	if (xmlDoc.getElementsByTagName('links')[0].getElementsByTagName('link')[0].childNodes[0]) {
		listLink = xmlDoc.getElementsByTagName('links')[0].getElementsByTagName('link')[0].childNodes[0].nodeValue;
	}
	var moreDesc = "";
	if (xmlDoc.getElementsByTagName('pager')[0].getElementsByTagName('more')[0].childNodes[0]) {
		moreDesc = xmlDoc.getElementsByTagName('pager')[0].getElementsByTagName('more')[0].childNodes[0].nodeValue;
	}
	if (moreDesc == "") {
		moreDesc = "more...";
	}
	var aLink = document.createElement('a');
	aLink.href = listLink;
	aLink.innerHTML = moreDesc;
	var tmpContainer = document.createElement('div');
	tmpContainer.appendChild(aLink);
	return tmpContainer.innerHTML;
};


// 取得 xml 裡的 pager data
FWUI.util.getPagerData = function(pager, func, panelId, windowId, cssSource, templateSource, xmlSource, params) {
	var count = parseInt(pager.getElementsByTagName('count')[0].childNodes[0].nodeValue);
	if (count == 0) return "";
	var maxPageItems = parseInt(pager.getElementsByTagName('maxPageItems')[0].childNodes[0].nodeValue);
	var currentPage = parseInt(pager.getElementsByTagName('currentPage')[0].childNodes[0].nodeValue);

	var url = "";
	if (xmlSource.indexOf("?") > 0) {
		url = xmlSource.substring(0, xmlSource.indexOf("?"));
	} else {
		url = xmlSource;
	}
	url += "?" + params + "&nt=2&pagesize=" + maxPageItems + "&pageno=";

	var tmpContainer = document.createElement('div');

	// 是否秀出 first, prev
	if (currentPage > _PAGERSIZE) {
		var first = document.createElement('a');
		first.id = "first";
		first.className = "first";
		first.href = "javascript:GoPage('" + func + "','" + panelId + "','" + windowId + "','" + cssSource + "','" + templateSource + "','" + url + "1','" + params + "')";
		first.innerHTML = "first&nbsp;&nbsp;";

		var prev = document.createElement('a');
		prev.id = "prev";
		prev.className = "prev";
		prev.href = "javascript:GoPage('" + func + "','" + panelId + "','" + windowId + "','" + cssSource + "','" + templateSource + "','" + url + (currentPage - _PAGERSIZE) + "','" + params + "')";
		prev.innerHTML = "prev_" + _PAGERSIZE + "&nbsp;&nbsp;";

		tmpContainer.appendChild(first);
		tmpContainer.appendChild(prev);
	}

	// 開始展開頁次
	var endPage = Math.floor(count / maxPageItems);
	if ((count % maxPageItems) > 0) endPage += 1;
	var start = (Math.floor(currentPage / _PAGERSIZE) * _PAGERSIZE) + 1;
	if ((currentPage % _PAGERSIZE) == 0) start = start - _PAGERSIZE;
	if (start > endPage) start = endPage - _PAGERSIZE + 1;
	var end = (Math.floor(currentPage / _PAGERSIZE) + 1) * _PAGERSIZE;
	if ((currentPage % _PAGERSIZE) == 0) end = end - _PAGERSIZE;
	if (end > endPage) end = endPage;
	for (var i = start; i <= end; i++) {
		if (i == currentPage) {
			var b = document.createElement('b');
			b.innerHTML = " " + i + " ";
			tmpContainer.appendChild(b);
		} else {
			var aLink = document.createElement('a');
			aLink.innerHTML = " " + i + " ";
			aLink.href = "javascript:GoPage('" + func + "','" + panelId + "','" + windowId + "','" + cssSource + "','" + templateSource + "','" + url + i + "','" + params + "')";
			tmpContainer.appendChild(aLink);
		}
	}

	// 是否秀出 next, last
	if (end < endPage) {
		var next = document.createElement('a');
		next.id = "next";
		next.className = "next";
		next.innerHTML = "&nbsp;&nbsp;next_" + _PAGERSIZE;
		if ((currentPage + _PAGERSIZE) > endPage) {
			next.href = "javascript:GoPage('" + func + "','" + panelId + "','" + windowId + "','" + cssSource + "','" + templateSource + "','" + url + endPage + "','" + params + "')";
		} else {
			next.href = "javascript:GoPage('" + func + "','" + panelId + "','" + windowId + "','" + cssSource + "','" + templateSource + "','" + url + (currentPage + _PAGERSIZE) + "','" + params + "')";
		}

		var last = document.createElement('a');
		last.id = "last";
		last.className = "last";
		last.href = "javascript:GoPage('" + func + "','" + panelId + "','" + windowId + "','" + cssSource + "','" + templateSource + "','" + url + endPage + "','" + params + "')";
		last.innerHTML = "&nbsp;&nbsp;last";

		tmpContainer.appendChild(next);
		tmpContainer.appendChild(last);
	}

	return tmpContainer.innerHTML;
}


// 取得 xml 裡的 item 資料
FWUI.util.getItemsData = function(items, pager) {
	var tmpContainer = document.createElement('div');
	var maxPageItems = parseInt(pager.getElementsByTagName('maxPageItems')[0].childNodes[0].nodeValue);
	var showPageItems = maxPageItems;
	var item = items.getElementsByTagName('item');
	if (maxPageItems > item.length) {
		showPageItems = item.length;
	}

	for (var i = 0; i < showPageItems; i++) {
		var cTitle = item[i].getElementsByTagName('title')[0].childNodes[0].nodeValue;
		var cLink = "";
		if (item[i].getElementsByTagName('link')[0].childNodes[0]) cLink = item[i].getElementsByTagName('link')[0].childNodes[0].nodeValue;
		var cGuid = "";
		if (item[i].getElementsByTagName('guid')[0].childNodes[0]) cGuid = item[i].getElementsByTagName('guid')[0].childNodes[0].nodeValue;
		var cPubDate = "";
		if (item[i].getElementsByTagName('pubDate')[0].childNodes[0]) cPubDate = item[i].getElementsByTagName('pubDate')[0].childNodes[0].nodeValue;
		

		// 目前只有 href & text 被實作
		if (cLink != "") {
            var aLink = document.createElement('a');
		    aLink.href = cLink;
		    aLink.innerHTML = cTitle;
		    tmpContainer.appendChild(aLink);
		} else {
		    //tmpContainer.appendChild(document.createTextNode(cTitle));
		    tmpContainer.innerHTML += cTitle;
		}
		//tmpContainer.appendChild(document.createElement('br'));
	}
	return tmpContainer.innerHTML;
};


// 將 html dom 文件依序抽取文字內容，並指定內容長度
FWUI.util.getContent = function(domString, limit) {
	if (domString.length <= limit) {
		return domString;
	}

	var str = "";
	if (domString) {
		var div = document.createElement('div');
		div.innerHTML = domString;
		_LIMITCOUNT = 0;
		div = lengthLimitRecursive(div, 100);
		str = div.innerHTML;
	}
	return str;
};





// 將 html dom 文件依序抽取文字內容，並指定內容長度
function lengthLimitRecursive(node, limit) {
	if (!node) {
		return "";
	}

	for (var i = 0; i < node.childNodes.length; i++) {
		var n = node.childNodes[i];
		if (_LIMITCOUNT >= limit) {
			node.removeChild(n);
			i = i - 1;
			continue;
		}

		if (n.nodeType == 3) {
			var len = n.nodeValue.length;
			if ((_LIMITCOUNT + len) > limit) {
				n.nodeValue = n.nodeValue.substring(0, (limit - _LIMITCOUNT));
				_LIMITCOUNT = limit;
			} else {
				_LIMITCOUNT += len;
			}
		} else {
			n = lengthLimitRecursive(n, limit);
		} 
	}

	return node;
}

// xml parser
function parseXMLString(xmlString) {
	var xmlDoc;
	try {
        xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
        xmlDoc.async = "false";
        xmlDoc.loadXML(xmlString);
    } catch(e) {
        var parser = new DOMParser();
		xmlDoc = parser.parseFromString(xmlString, "text/xml");
    }
	return xmlDoc;
}

// 換頁
function GoPage(func, panelId, windowId, templateSource, xmlSource, cssSource, params, _cFunc) {
	eval("new " + func + "(panelId, windowId, templateSource, xmlSource, cssSource, params, _cFunc);");
}