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的原型指向这个实例,这种实现继承的方法叫“原型链”法。 - 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 实现...//<?xml version="1.0" encoding="utf-8"?>
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文件,而只是一个节点,则加上 \u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e
if (isXmlContext.indexOf("<?xml") < 0) {isXmlContext = "\u003c?xml 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();