//定义返回信息处理对象
Buffalo.Reply = Class.create();
Buffalo.Reply.prototype = {
// 初始化 Buffalo.Reply调用的方法,已经很多次用到这个方法了,初始化方法的参数就是服务短的返回信息
//xhr :包含返回信息的 XmlHttp 对象
initialize: function(xhr) {
this._isFault = false;
this._type = "null";
this._objects = [];
this._objectNodes = [];
this._source = xhr.responseText;
//返回的XML字符串是否DOM化了
var root = xhr.responseXML ? xhr.responseXML.documentElement :
this.constructNodeFromXmlStringInIEOrFF(this._source);
this.dataNode = root.firstChild;
//获取节点的类型 在后台已经设置好了
this._type = this._getType(this.dataNode);
},
//将xml字符串的转化为dom层次结构对象
constructNodeFromXmlStringInIEOrFF: function(xmlString) {
var xmldoc = XmlDocument.create();
xmldoc.async=false;
xmldoc.loadXML(xmlString);
return xmldoc.documentElement;
},
getType: function() { return this._type; },
//获取结果的服务器的返回结果
getResult : function() { return this.deserialize(this.dataNode); },
isFault : function() { return (this._type == "fault"); },
isNull: function() { return (this._type == "null"); },
//获取 服务器放回的 responseText 信息
getSource : function() { return this._source; },
//根据根节点 反序列化 相关操作
deserialize: function(dataNode) {
var ret;
//获取节点数据的类型 然后根据不同的类型 初始化相关的数据
var type = this._getType(dataNode);
switch (type) {
case "boolean": ret = this.doBoolean(dataNode); break;
case "date": ret = this.doDate(dataNode); break;
case "double": ret = this.doDouble(dataNode); break;
case "int":
case "long":
ret = this.doInt(dataNode);
break;
case "list": ret = this.doList(dataNode); break;
case "map": ret = this.doMap(dataNode); break;
case "null": ret = this.doNull(dataNode); break;
case "ref": ret = this.doRef(dataNode); break;
case "string": ret = this.doString(dataNode);break;
case "xml": ret = this.doXML(dataNode); break;
case "fault": ret = this.doFault(dataNode); break;
default: ;
}
return ret;
},
//获取节点的数据类型
_getType : function(dataNode) {
return dataNode.tagName.toLowerCase();
},
//获取节点的文本值
getNodeText :function(dataNode) {
if (dataNode && dataNode.hasChildNodes()) {
var s = "";
for (var i = 0; i < dataNode.childNodes.length; i++)
{
s += new String(dataNode.childNodes.item(i).nodeValue);
}
//alert("tagName = " + dataNode.tagName+"nodeValue :"+ s);
return s;
} else {
return null;
}
},
//获取布尔值 true 或 false
doBoolean : function (dataNode) {
var value = this.getNodeText(dataNode);
return (value == "1");
},
doDate : function (dataNode) {
var dateStr = this.getNodeText(dataNode);
var year = parseInt(dateStr.substring(0,4),"10");
var month = parseInt(dateStr.substring(4,6),"10") - 1;
var day = parseInt(dateStr.substring(6,8),"10");
var hour = parseInt(dateStr.substring(9,11),"10");
var minute = parseInt(dateStr.substring(11,13),"10");
var second = parseInt(dateStr.substring(13,15),"10");
var d = new Date(year, month, day, hour, minute, second);
return d;
},
doDouble : function (dataNode) {
var value = this.getNodeText(dataNode);
return parseFloat(value);
},
doInt: function (dataNode) {
var value = this.getNodeText(dataNode);
return parseInt(value);
},
//处理数组的时候 我认为应该考虑内存的释放,如果数据量比较大(30W个元素),同一个浏览器没执行改函数一次 内存占有率都会涨40MB左右
doList: function (dataNode) {
var arr = new Array();
this._objects[this._objects.length] = arr;
var children = dataNode.childNodes;
arr[Buffalo.BOCLASS] = this.getNodeText(children[0]);
for (var i=2; i < children.length; i++) {
arr[arr.length] = this.deserialize(children[i]);
}
return arr;
},
doMap: function (dataNode) {
var obj = new Object();
this._objects[this._objects.length] = obj;
var attrs = dataNode.childNodes;
obj[Buffalo.BOCLASS] = this.getNodeText(attrs[0]);
for (var i = 1; i < attrs.length; i+=2) {
obj[this.getNodeText(attrs[i])] = this.deserialize(attrs[i+1]);
}
return obj;
},
doNull: function (dataNode) { return null; },
doRef: function (dataNode) {
var value = this.getNodeText(dataNode);
var idx = parseInt(value);
return this._objects[idx];
},
doString: function (dataNode) {
var value = this.getNodeText(dataNode);
if (value == null) {
return "";
}
return (value);
},
//如果返回的是XML形式的字符串 需要使用unescape()方法解码用 escape 方法进行了编码的 String 对象
doXML : function (dataNode) {
var value = this.getNodeText(dataNode);
return unescape(value);
},
doFault : function (dataNode) {
var code = this.getNodeText(dataNode.childNodes[1]);
var msg = this.getNodeText(dataNode.childNodes[3]);
var detail = this.deserialize(dataNode.childNodes[5]);
return new Buffalo.Fault(code, msg, detail);
}
,
clearResponse:function(){
this._objects = null ;
}
}
// 显示 后台返回的 错误信息 对于调式比较有用
Buffalo.Fault = Class.create();
Buffalo.Fault.prototype = {
initialize: function(code, message, detail) {
this.code = code;
this.message = message;
this.detail = detail;
},
toString: function() {
return "Buffalo.Fault:[code=" + this.code + ", message=" + this.message + ", detail=" + this.detail+"]";
}
}
// 为 Buffalo类添加一个绑定的方法,如果需要绑定页面的元素可以使用该方法调用 后台的服务
Object.extend(Buffalo.prototype, {
bindReply : function(service, params, bindElemId, options) {
this.remoteCall(service, params, function(reply) {
Buffalo.Bind.bind(bindElemId, reply.getResult(), options);
})
}
});
//将调用的服务的返回值 与 页面的表单元素进行绑定
//设置的表单类型可以是text hidden password checkbox radio TEXTAREA TABLE SELECT DIV SPAN FORM中的任何一种。
Buffalo.Bind = {
bind : function(elementId, bindValue, options) {
var elem = $(elementId);
switch(elem.tagName) {
case "INPUT":
switch (elem.type.toLowerCase()) {
case "text": ;
case "hidden": ;
case "password": Buffalo.BindFactory.bindText(elem, bindValue); break;
case "checkbox": ;
case "radio": Buffalo.BindFactory.bindRadioOrCheckbox(elem, bindValue); break;
}
break;
case "TEXTAREA":
Buffalo.BindFactory.bindText(elem, bindValue);
break;
case "TABLE":
Buffalo.BindFactory.bindTable(elem, bindValue);
break;
case "SELECT":
Buffalo.BindFactory.bindSelect(elem, bindValue, options);
break;
case "DIV":
case "SPAN":
elem.innerHTML = bindValue;
break;
case "FORM":
Buffalo.Form.bindForm(elem, bindValue);
}
}
}
Buffalo.BindFactory = {
reportError: function(elem, value, msg) {
throw "Data bind failed: "+msg;
},
bindText: function(elem, value) {
elem.value = value;
},
bindRadioOrCheckbox: function(elem, value) {
elem.checked = Buffalo.BindFactory.checkTrue(value);
},
bindSelect : function(elem, value, options) {
//TODO: Check the data type
if (typeof(value) != "object" || value.constructor != Array) {
this.reportError(elem,value,"Array Type Needed for binding select!");
}
// 初始化select标签前 先清除其原来的所有标签
while (elem.childNodes.length > 0) {
elem.removeChild(elem.childNodes[0]);
}
// bind data
for (var i = 0; i < value.length; i++) {
var option = document.createElement("OPTION");
if (options && options.binder) {
options.binder(value, option, i);
} else {
var data = value[i];
if (typeof(data) != 'object') {
option.value = data;
option.text = data;
} else {
option.value = data[elem.getAttribute("jvalue")];
option.text = data[elem.getAttribute("jtext")];
if (Buffalo.BindFactory.checkTrue(data.selected)) {
option.selected = true;
}
}
}
elem.options.add(option);
}
},
bindTable: function(elem, value) {
var jHeight = parseInt(elem.getAttribute("jheight"));
var dataHeader = [];
var tBody = elem.getElementsByTagName("TBODY")[0];
// clear the generated rows
if (elem.getElementsByTagName("TBODY").length > 0) {
while (tBody.rows.length > jHeight) {
tBody.deleteRow(jHeight);
}
}
if (jHeight == 0) { // if table is null, push the data to the tables.
for (var x in value[0] ) {
dataHeader[dataHeader.length] = x;
}
var hTr = elem.insertRow(elem.rows.length);
for (var i = 0; i < dataHeader.length; i++) {
var td = hTr.insertCell(hTr.cells.length);
td.innerHTML = dataHeader[i];
}
for (var i = 0; i < value.length; i++) {
var tr = elem.insertRow(elem.rows.length);
var data = value[i];
for (x in data ) {
var td = tr.insertCell(tr.cells.length);
td.innerHTML = data[x];
}
}
}
if (jHeight == 1) { // if there is only one line, first line is header(every td indicate by a jtext property)
var headerTR = tBody.rows[0];
for (var i = 0; i < headerTR.cells.length ; i++ ) {
dataHeader[dataHeader.length] = headerTR.cells[i].getAttribute("jtext");
}
for (var i = 0; i < value.length; i++) {
var tr = tBody.insertRow(tBody.rows.length);
var data = value[i];
for (var j = 0; j < dataHeader.length; j++ ) {
var td = tr.insertCell(tr.cells.length);
td.innerHTML = data[dataHeader[j]];
}
}
}
if (jHeight == 2) { // two lines, first line is header, the second is style
var headerTR = tBody.rows[0];
for (var i = 0; i < headerTR.cells.length ; i++ ) {
dataHeader[dataHeader.length] = headerTR.cells[i].getAttribute("jtext");
}
for (var i = 0; i < value.length; i++) {
var tr;
if (i == 0) { // if the first row
tr = elem.rows[1];
} else { // else copy the first row
tr = elem.rows[1].cloneNode(true);
}
if (i > 0) {
tBody.appendChild(tr);
}
var data = value[i];
for (var j = 0; j < tr.cells.length; j++ ) {
var td = tr.cells[j];
td.innerHTML = data[dataHeader[j]];
}
}
}
if (jHeight >= 3) { // more than 3 rows, first header, second and third is odd/even style, other lines ommited.
var headerTR = tBody.rows[0];
for (var i = 0; i < headerTR.cells.length ; i++ ) {
dataHeader[dataHeader.length] = headerTR.cells[i].getAttribute("jtext");
}
for (var i = 0; i < value.length; i++) {
var tr;
if (i == 0) { // 1st row
tr = tBody.rows[1];
} else if (i == 1) { // 2nd row
tr = tBody.rows[2];
} else if ( i % 2 == 0) { // get the 1st row
tr = tBody.rows[1].cloneNode(true);
} else if (i % 2 == 1) { // the 2nd row
tr = tBody.rows[2].cloneNode(true);
}
if (i > 1) {
tBody.appendChild(tr);
}
var data = value[i];
for (var j = 0; j < tr.cells.length; j++ ) {
var td = tr.cells[j];
td.innerHTML = data[dataHeader[j]];
}
}
}
},
checkTrue: function(value) {
var ret = false;
switch (typeof(value)) {
case 'boolean': ret = value; break;
case 'string': ret = (value == true || value == "1" || value == "true" || value == "yes"); break;
case 'number': ret = (parseInt(value) == 1); break;
default: ret = false;
}
return ret;
}
}
Buffalo.bind = Buffalo.Bind.bind; /*capable with the old version, deprecated*/
Buffalo.View = Class.create();
Buffalo.View.LAST_VIEWNAME = null;
Buffalo.View.CURRENT_VIEW = null;
Buffalo.View.HOME_VIEW = null;
Buffalo.View.HISTORY_IFRAME_ID = "buffalo-view-history-iframe";
Buffalo.View.iframeLoaded = function(loc) {
var url = loc.href;
var idx = url.indexOf("?");
var viewName = "";
if (idx > -1) {
viewName = url.substring(idx+1);
}
if (viewName == "") {
viewName = Buffalo.View.HOME_VIEW;
}
if (Buffalo.View.CURRENT_VIEW != null) {
Buffalo.View.CURRENT_VIEW.doSwitchPart(viewName);
}
}
Buffalo.View.prototype = {
initialize:function(buffaloObj) {
this.buffalo = buffaloObj;
},
switchPart: function(partId, viewName, addToHistory) {
this.partId = partId;
this.viewName = viewName;
if (typeof(addToHistory) == "undefined" || addToHistory == true) {
this.addToHistory = true;
} else {
this.addToHistory = false;
}
if (Buffalo.View.LAST_VIEWNAME == null) {
/* the first visit view is home view */
Buffalo.View.HOME_VIEW = viewName;
/* The first view, don't add to history */
this.doSwitchPart(viewName);
Buffalo.View.LAST_VIEWNAME = viewName;
return;
}
Buffalo.View.CURRENT_VIEW = this;
if (this.addToHistory) {
if ($(Buffalo.View.HISTORY_IFRAME_ID)) {
var iframesrc=$(Buffalo.View.HISTORY_IFRAME_ID).src;
var newUrl = iframesrc;
var idx = iframesrc.indexOf("?");
if (idx > -1) {
newUrl = iframesrc.substr(0,idx);
}
newUrl += "?" + viewName;
$(Buffalo.View.HISTORY_IFRAME_ID).src = newUrl;
} else {
var msg = "It seems that you havent add the buffalo-blank.html as an Iframe for browser history.";
msg += "/nSo this view cannot add to browser history.";
msg += "/n/nTo prevent this dialog, use buffalo.switchPart(partId, viewName, false) or ";
msg += "add the buffalo-blank.html to your main page with id 'buffalo-view-history-iframe'.";
alert(msg);
}
}
this.doSwitchPart(viewName);
Buffalo.View.LAST_VIEWNAME = viewName;
},
doSwitchPart: function(viewName) {
if (Buffalo.View.LAST_VIEWNAME == viewName) {
return ;
}
this.transport = XmlHttp.create();
var nonCachedViewName = viewName;
try {
/*Fix for the IE cache*/
if (/MSIE/.test(navigator.userAgent)) {
var bfViewHackKey = "_bfviewhackkey_=" + (new Date()).getTime();
if (viewName.indexOf('?') > -1) {
nonCachedViewName += "&" + bfViewHackKey;
} else {
nonCachedViewName += "?" + bfViewHackKey;
}
}
this.transport.open("GET", nonCachedViewName, this.buffalo.async);/*use get for static page*/
} catch (e) {
var msg = "Buffalo View Error: /n/n Cannot find view with name: " + "[" + viewName + "]";
alert(msg);
}
this.transport.send(null);
if (this.buffalo.async) {
this.transport.onreadystatechange = this._viewHandle.bind(this);
this.buffalo.events["onLoading"](true);
} else {
this._processView();
}
Buffalo.View.LAST_VIEWNAME = viewName;
},
_viewHandle : function(){
this._processView();
},
_processView : function() {
this.buffalo.events["onLoading"](false);
if (this.transport.readyState == 4) {
if (this.transport.status == '200') {
var data = this.transport.responseText;
this._showView(this.partId, this.viewName, data);
} else {
this.buffalo.events["onError"](this.transport);
}
}
},
_showView: function(partId, viewPath, viewData) {
var regexp1 = /