面向对象JS编程基类实现
web打印(3),面向对象js:名字空间、类定义、继承、xml分析xmlparserbase基类实现
javascript代码,可以写在html里,也可以写在*.js文件里,大家没有有遇到引用了别人或自己的js文件时,发现定义了同样的变量,例如 var myobject;由于javascript不像c#是强类型面向对象编程语言,更多的是像c的过程性结构化编程语言,随处定义变量,不可避免定义重复的变量名,这种重复的变量会导致严重的后果。所以,像c#一样,引入名字空间,将类定义到名字空间下,将变量定义到类中,不同类,定义了相同的变量互不受影响。
面向对象最大的特点是抽象,最大优点是可复用性。既然是做打印元素,例如文本、标签、表格、图片、标尺等等,他们都有一个共同的特征,就是用xml去描述他们的属性特点,而分析xml后,获得一个打印对象。所以,xmlparserbase基类,抽象了xmlnode,作为类的属性,然后继承ixmlparser,实现接口定义的方法parser(),分析xml后将相关标签写入tag属性。由于后续要做大量的xml分析,所以,xmlparserbase基类,提供读取xml文件、xml字符串、xml节点的大量实用方法,供继承于xmlparserbase的子类使用。
字空间/*顶层命名空间*/
var goldprinter =goldprinter || window.goldprinter || {};
/*子命名空间,可嵌套定义*/
goldprinter.drawing = goldprinter.drawing || window.goldprinter.drawing || {};
goldprinter.xmlparser = goldprinter.xmlparser || window.goldprinter.xmlparser || {};
以上定义方法需要说明的是,以var goldprinter =goldprinter || window.goldprinter || {}为例,在重复定义goldprinter时避免被误覆盖掉。这样便能很方便的在多个文件里定义命名空间了。 类定义
在上文web打印(2),打印核心架构--xml分析器及打印元素uml类图,接口及实现中,其实已定义了ixmlparser类,并且用js实现ixmlparser时,我们用到了如下语句:
goldprinter.throw.msg("这是ixmlparser的parse() ,接口类不要实例化!\r\n类型:" + typeof (this) + "真实类名" + this.gettype());
这其实是调用于goldprinter名字空间下throw类的一个msg()方法。在后续的开发实现中,我们经常用于如下两个类,类似c#的静态类及静态方法。
goldprinter.throw = { msg: function (message) { alert(message);} };
goldprinter.messagebox = { show: function (message) { alert(message); }, debug: function (message) { alert(message); } };
throw 类专门用于抛出异常时对话框,以提示开发者自己,messagebox类用于显示对话框,用于提示客户端正在使用的操作用户。
综述,ixmlparser类和throw、messagebox类,是两类不同写法的类。前者相当于是一个模版,可以复制出很多具有相同模版又可以改变模版中属性值的对象,这种类可实例化,只能使用实例对象;而后者,不用把模版复制直接可以使用。 继承/*
* 表示分析处理用xml节点描述特征的对象的基类。
*/
jxmlparser.xmlparserbase = function (xmlnode, tag) {
//模拟c#,获取实例的类型,js如果不实现,都返回object
this.gettype = function () { return "goldprinter.xmlparser.xmlparserbase"; };
/*获取或设置描述对象特征的xml节点。*/
this.xmlnode = "";
/*获取或设置报表设计器的类型。*/
this.reportdesigner = jxmlparser.reportdesigner.goldprinter;
//标签
this.tag = {};
if (xmlnode) {
this.xmlnode = xmlnode;
}
if (tag) {
this.tag = tag;
}
//其他代码..
}
//继承于接口ixmlparser
jxmlparser.xmlparserbase.prototype = new jxmlparser.ixmlparser();
说明:
jxmlparser.xmlparserbase = function (xmlnode, tag) {},用于定义一个类xmlparserbase ,他在goldprinter.xmlparser名字空间下,名字空间简写为jxmlparser。
new jxmlparser.ixmlparser();表示创建ixmlparser的一个实例,将xmlparserbase的原型指向这个实例,这种实现继承的方法叫“原型链”法。
下面是其实现的全部js代码。
/*
* 表示分析处理用xml节点描述特征的对象的基类。
*/
jxmlparser.xmlparserbase = function (xmlnode, tag) {
//#region 实现...
//模拟c#,获取实例的类型,js如果不实现,都返回object
this.gettype = function () { return "goldprinter.xmlparser.xmlparserbase"; };
/*获取或设置描述对象特征的xml节点。*/
this.xmlnode = "";
/*获取或设置报表设计器的类型。*/
this.reportdesigner = jxmlparser.reportdesigner.goldprinter;
//标签
this.tag = {};
if (xmlnode) {
this.xmlnode = xmlnode;
}
if (tag) {
this.tag = tag;
}
/*对tag进行分析,并附加上reportdesigner,如果需要可以调用,一般无用。*/
this.tagparse = function () {
//#region 实现...
var node = this.getxmlnode();
if (node) {
//在属性中搜
var otag = this.getxmlnodeattributevalue(node, "tag");
var oreportdesigner = this.getxmlnodeattributevalue(node, "reportdesigner");
//属性中没,在子节点中
if (otag == "") {
otag = this.getxmlnodechildnodevalue(node, "tag");
}
if (oreportdesigner == "") {
oreportdesigner = this.getxmlnodechildnodevalue(node, "reportdesigner");
}
if (otag != "") {
this.tag = otag
}
if (oreportdesigner != "") {
this.reportdesigner = oreportdesigner;
}
}
//#endregion 实现...
};
this.parse = function () {
//js方法,不会调用基类已重写的方法。所以,继承此类的方法,重写parse时,手动强制调用parentclass.parse()
this.tagparse(); //c#中xmlparserbase是抽象类,所以没有放在模板方法中调用
goldprinter.debugmodel.msg("这是xmlparserbase的parse() ,抽象类,请在子类实现parse()方法!\r\n类型:" + typeof (this) + "真实类名" + this.gettype());
return this;
};
var mxmlparsenode = undefined;
/*获取xmlnode,当其为xml字符串时,自动将期转换为节点,将缓存,如果重新改变了xmlnode不使用缓存,则要调用setxmlnode()*/
this.getxmlnode = function () {
var node = mxmlparsenode;
if (node == undefined) {
node = this.xmlnode;
}
else {
return mxmlparsenode;
}
if (node && typeof (node) == "string") {
node = this.selectrootnode(node, false);
//缓存
mxmlparsenode = node;
}
return node;
};
/*设置xmlnode属性,并清空节点缓存*/
this.setxmlnode = function (xmlnode) { mxmlparsenode = undefined; this.xmlnode = xmlnode; };
/*用xml文件设置元素,xmlnode属性默认取其根结点,第一参数表示表示金质打印通的元素集合文件或文件文本内容,第二参数为true,表示文件名,否则为文件具体内容*/
this.selectrootnode = function (xmlfilename, isxmlfileorcontext) {
//#region 实现...
//
if (xmlfilename == undefined) return;
var isxmlcontext = xmlfilename;
if (isxmlfileorcontext) {
if (window.xmlhttprequest) {// ie7+, firefox, chrome, opera, safari
xmlhttp = new xmlhttprequest();
}
else {//ie6, ie5
xmlhttp = new activexobject("microsoft.xmlhttp");
}
xmlhttp.open("get", isxmlcontext, false);
xmlhttp.send();
mxmldoc = xmlhttp.responsexml;
}
else {
/*
//不是xml文件,而只是一个节点,则加上 \u003cxml version=\"1.0\" encoding=\"utf-8\"\u003e
if (isxmlcontext.indexof("
isxmlcontext = "\u003cxml version=\"1.0\" encoding=\"utf-8\"\u003e" + isxmlcontext;
}
*/
if (window.domparser) {//firefox, chrome, opera, safari
parser = new domparser();
mxmldoc = parser.parsefromstring(isxmlcontext, "text/xml");
}
else {// internet explorer
mxmldoc = new activexobject("microsoft.xmldom");
mxmldoc.async = "false";
mxmldoc.loadxml(isxmlcontext);
}
}
var rootnode = mxmldoc.documentelement;
//rootnode.childnodes[i]
return rootnode;
//#endregion 实现...
}
//根据节点属性名取得节点对象,属性名不区分大小写,找不对则返回null。
this.getxmlnodeattributebyname = function (node, findattributename) {
//#region 实现...
if (node) {
var attributename = "";
for (var i = 0 ; i < node.attributes.length; i++) {
attributename = node.attributes[i].name.tolowercase();
if (findattributename.tolowercase() == attributename) {
return node.attributes[i];
}
}
}
return null;
//#endregion 实现...
};
//读取节点的属性值,如果属性不存在则返回空串""。
this.getxmlnodeattributevalue = function (node, attributename) {
//#region 实现...
if (node) {
var attribute = this.getxmlnodeattributebyname(node, attributename);
if (attribute) {//attribute.nodetype == 2
return attribute.value; //attribute.nodevalue
}
}
return "";
//#endregion 实现...
};
// 根据子节点名取得节点的子节点对象,子节点名不区分大小写,找不对则返回null。
this.getxmlnodechildnodebyname = function (node, childnodename) {
//#region 实现...
if (node) {
var son = undefined;
var sonname = undefined;
var childnodevalue = undefined;
for (var i = 0 ; i < node.childnodes.length; i++) {
son = node.childnodes[i];
sonname = son.nodename;
if (son.nodetype != 1 || sonname == undefined) {
continue;
}
sonname = sonname.tolowercase();
if (sonname == childnodename.tolowercase()) {
return son;
}
}
}
return null;
//#endregion 实现...
};
//读取节点子节点的值,如果不存在则返回空串""。
this.getxmlnodechildnodevalue = function (node, childnodename) {
//#region 实现...
if (node) {
var childnode = this.getxmlnodechildnodebyname(node, childnodename);
if (childnode) {
return childnode.textcontent;
}
}
return "";
//#endregion 实现...
};
// 选择匹配xml文档中指定节点标记名的第一个节点。注意节点名区分大小写的。
this.selectsinglenodebynodename = function (xmlfilename, nodename) {
if (node) {
goldprinter.throw.msg("实现ing");
}
return undefined;
};
// 在xml文档中查找匹配节点标记名指定属性值的第一个节点。注意节点名属性及值都是区分大小写的。
this.selectsinglenodebyattribute = function (xmlfilename, nodename, attributename, attributevalue) {
if (node) {
goldprinter.throw.msg("实现ing");
}
return undefined;
};
/*只为与c#保持一致,在js意义不大。c#中从预定义的颜色名如red、gold或十六进制的颜色如#0000ff或以逗号分隔的三色值,如255,255,255 创建一个system.drawing.color结构。*/
this.getcolorfrom = function (color) {
if (color) {
var arr = color.split(',');
if (arr.length >= 2) {
if (color.tolowercase().indexof("rgb") < 0) {
return "rgb(" + color + ")";
}
}
return color;
}
return "black";
};
}
//继承于接口ixmlparser
jxmlparser.xmlparserbase.prototype = new jxmlparser.ixmlparser();
上一篇: 百度地图API详解之地图标注
下一篇: 关于Htmlclassid命名规范案例