JS+XML打造QQ个性通信录
一接触XML就喜欢上它,当时还在本版发了叫JS+XML+HTML=?的帖,大概介绍用JS操纵XML实现查询功能做通信录。现在重写,把它嵌入到QQ面板,成为这样的效果: 共享共享…… 整个程序包括 Communication.htm,Communication.css,Communication.xml 三个主要文件和一些图片文件。先介绍存放数据的文件 Communication.xml
XML全名是:eXtensible Markup Language(可扩展标识语言),它和网页超文本标记语言HTML有点相似。(不作详细介绍,有兴趣的可以搜索相关文章)
假设你的朋友分为三类,分别是:同学,同事,其它朋友
所以XML数据文件可以为这样:
Communication.xml
<?xml version="1.0" encoding="gb2312"?>
<通信录>
<同学>
<个人信息>
<姓名 性别="男">陈一</姓名>
<出生日期>1983-8</出生日期>
<住址>湛江</住址>
<家里电话>0729-3201928</家里电话>
<手机号码>13756875467</手机号码>
<电子邮箱>chengone@21cn.com</电子邮箱>
<QQ号码>82521492</QQ号码>
</个人信息>
<个人信息>
<姓名 性别="男">李二</姓名>
<出生日期>1983-1-12</出生日期>
<住址>汕头</住址>
<家里电话>0750-2596329</家里电话>
<手机号码>13637896451</手机号码>
<电子邮箱>litwo@163.com</电子邮箱>
<QQ号码>260117983</QQ号码>
</个人信息>
</同学>
<同事>
<个人信息>
<姓名 性别="女">王三</姓名>
<出生日期>1986-5-6</出生日期>
<住址>广州市</住址>
<家里电话>020-88158546</家里电话>
<手机号码>1392585676</手机号码>
<电子邮箱>wangthree@hotmail.com</电子邮箱>
<QQ号码>7454652657</QQ号码>
</个人信息>
<个人信息>
<姓名 性别="女">何四</姓名>
<出生日期> 1985-2-5</出生日期>
<住址>北京</住址>
<家里电话>010-88816594</家里电话>
<手机号码>13512586555</手机号码>
<电子邮箱>hefour@263.net</电子邮箱>
<QQ号码>764354985</QQ号码>
</个人信息>
</同事>
<其它朋友>
<个人信息>
<姓名 性别="男">陈四</姓名>
<出生日期>1983-5-23</出生日期>
<住址>电白</住址>
<家里电话>0714-85654685</家里电话>
<手机号码>13929634673</手机号码>
<电子邮箱>chengfour@263.net</电子邮箱>
<QQ号码>2824368488</QQ号码>
</个人信息>
<个人信息>
<姓名 性别="男">何时</姓名>
<出生日期>1986-6-3</出生日期>
<住址>广州</住址>
<家里电话>020-87685456</家里电话>
<手机号码>13752856285</手机号码>
<电子邮箱>heshi@263.com</电子邮箱>
<QQ号码>423719510</QQ号码>
</个人信息>
</其它朋友>
</通信录>
上面的XML文档可以理解成这样的树形结构:
其中元素个人信息的子元素没有画出,其子元素分别是:姓名,出生日期,住址,家里电话,手机号码,电子邮箱,QQ号码。这几个元素都没有子元素,而只是有值(其中姓名还有一个属性—性别)。
因为用JS操纵XML时是采用DOM文档对象模型,所以要先知道这个文档的结构。
[ 本帖最后由 powerwind 于 2006-8-6 13:17 编辑 ] 限于篇幅,略去外观的设计,也就是略去CSS样式文件 Communication.css 现在就只剩下 Communication.htm和 Communication.js 两个文件了。
因此,只给出重要代码
Communication.htm
这里应该是htm(已改了,PPT应该没意见吧……)
---MODIFYBYiptton
<html>
<head>
<link href="Communication.css" type="text/css" rel="stylesheet" />
<script language="javascript" src="Communication.js"></script>
</head>
<body>
<table><tr><td>
<input id="inputText" type="text" onmouseover="this.focus()" onfocus="this.select()" value="请输入关键字查询" />
</td></tr>
<tr><td width="174">
<select id="styles">
<option value="Name" selected>姓名
<option value="FamilyName">姓氏
<option value="Cellphone">手机号码
<option value="QQ">QQ号码
</select>
<input type="image" src="search_btn.gif" style="cursor:hand" onclick="find(styles.value,inputText.value)" />
</td></tr>
<tr><td>
<select id="classes">
<option value="all" selected>全部
<option value="classmate">同学
<option value="workmate">同事
<option value="others">其它朋友
</select>
<a href="javascript:seeAll(classes.value)">查看</a>
</td></tr>
</table>
</body>
</html>
[ 本帖最后由 iptton 于 2006-8-17 19:38 编辑 ] Communication.js 文件是操纵XML的 javascript 程序代码,有两个重要函数。
Communication.js
var XDoc = null; //xmldom文档对象
var xmlFile="Communication.xml";//XML文件
var tableHead="<table align='center' style='border-collapse:collapse' bordercolor='#ffe366' border='2'><tr style='font-size:16pt;color:#f90000;'><th>姓名</th><th>性别</th><th>出生日期</th><th>住址</th><th>家里电话</th><th>手机号码</th><th>电子邮箱</th><th>QQ号码</th></tr><tr>";
//指定关键字查找
function find(classes,keyWords) //classes:查找类别,keyWords:查找关键字
{
if(XDoc==null)
{
XDoc=new ActiveXObject("Microsoft.xmldom");
XDoc.load(xmlFile);
}
if(keyWords==null||(keyWords=Trim(keyWords)).length>11||keyWords.length<1){
window.alert("输入有误,请重新输入");
return false;
}
var XML_root=XDoc.documentElement; //根元素(通信录)
var Level1nodes=XML_root.childNodes; //根以下的所有子集(同学,同事,其它朋友)
var rootLen=Level1nodes.length; //子元素个数
var Level1node,Level1nodes,Level2node,Level2nodes,Level3node,Level3nodes;
var tableStr=tableHead,familyname="",mystring=""
var count=1; //以第几个元素的值来查找
for(var c=0;c<rootLen;c++) //根目录下的子目录循环查找
{
Level2node=Level1nodes.nextNode(); //根下的(同学或同事或其它朋友)
Level2nodes=Level2node.childNodes; //(同学或同事或其它朋友)下的所有个人信息
var NodeLen=Level2nodes.length; //个人信息的个数
for(var i=0;i<NodeLen;i++)
{
//第i个个人信息,currentNode保存当前结点
currentNode=Level3node=Level2nodes.nextNode();
Level3nodes=Level3node.childNodes; //个人信息下的所有子集
if(classes=="QQ")count=7;
else if(classes=="Cellphone")count=5;
for(var j=0;j<count;j++)
Level3node=Level3nodes.nextNode();
familyname=Level3node.text;
if(classes=="FamilyName") //按姓氏查找
{
familyname=Trim(familyname).charAt(0);
keyWords=keyWords.charAt(0);
}
if(familyname==keyWords)
{
Level3nodes=currentNode.childNodes;
for(var j=0;j<Level3nodes.length;j++)
{
Level3node=Level3nodes.nextNode();
if(j==0)mystring+="<td>"+Level3node.text+"</td><td>"+ Level3node.attributes.value+"</td>";
else mystring+="<td>"+Level3node.text+"</td>";
}
mystring+="</tr>";
}
}
}
//输出结果
if(mystring.length<10)
{
window.alert("对不起,以"+classes+"来查找,没有找到'"+keyWords+"'的相关信息\n");
return false;
}
mystring=tableStr+mystring+"</table>";
var newWin=window.showModelessDialog("a","","dialogWidth=55;dialogHeight=20")
newWin.document.write("<style type='text/css'>td{font-size:16pt;color:#2235f8}</style>");
newWin.document.write("<body background='communication.jpg'>");
newWin.document.write("<br><h2 align='center' style='color:blue'>查询结果</h2>");
newWin.document.write(mystring);
return false;
}
//去除首尾空格
function Trim(str)
{
var ss=String(str);
return ss.replace(/(^\s*)|(\s*$)/g, "");
}
//按类别查看(和 find 函数相似,不再注释)
function seeAll(classes){ //classes:查找类别
if(XDoc==null)
{
XDoc=new ActiveXObject("Microsoft.xmldom");
XDoc.load(xmlFile);
}
var result=tableHead;
var currentNode;
var Level1nodes,Level2node,Level3nodes;
var count=0;
if(classes=="classmate")count=1;
else if(classes=="workmate")count=2;
else if(classes=="others")count=3;
var XML_root=XDoc.documentElement;
var Level1nodes=XML_root.childNodes;
if(count!=0)
{
for(var i=0;i<count;i++)
{
Level2node=Level1nodes.nextNode();
}
result+=parseNode(Level2node.childNodes,Level2node.childNodes.length);
}else
{
for(var i=0;i<Level1nodes.length;i++)
{
Level2node=Level1nodes.nextNode();
result+=parseNode(Level2node.childNodes,Level2node.childNodes.length);
}
}
outPut(result);
}
//输出
function outPut(result)
{
result+="</table></body><br>";
var w=screen.width-10,h=screen.height-10;
var newWin=window.showModelessDialog("a","","dialogWidth="+w+";dialogHeight="+h)
newWin.document.write("<style type='text/css'>td{font-size:16pt;color:#2235f8}h2{color:blue;text-align:center}</style>");
newWin.document.write("<body background='communication.jpg'>");
newWin.document.write("<br><h2>通信录</h2>");
newWin.document.write(result);
newWin.document.close();
}
//解析节点
function parseNode(nodes,nodesLen)
{
var Level3nodes,len,result="";
for(var j=0;j<nodesLen;j++)
{
Level3nodes=nodes.nextNode().childNodes;
var len=Level3nodes.length;
for(var k=0;k<len;k++)
{
currentNode=Level3nodes.nextNode();
if(k==0)result+="<td>"+currentNode.text+"</td><td>"+currentNode.attributes.value+"</td>";
else result+="<td>"+currentNode.text+"</td>";
}
result+="</tr><tr>";
}
return result;
}
这样,就基本上完成了一个网页了。至于如何嵌入QQ面板,==
[ 本帖最后由 powerwind 于 2006-8-1 15:57 编辑 ] 很有创意的原创内容.加精了...
PS...楼主别不好意思,别因为是自己的文章就不敢加精.写得好就要让大家都知道... 楼上的,我还没有写完呢!呵呵~
待续。。。 说真的……
POWERWIND师兄的界面做得不怎么样……
跟偶的水平无甚差距……
当然,后面的代码实现…… 原帖由 iptton 于 2006-8-1 00:37 发表
说真的……
POWERWIND师兄的界面做得不怎么样……
跟偶的水平无甚差距……
当然,后面的代码实现……
Wool 师兄说,会写程序的人很多都不会做界面的。呵呵~
所以界面做得不好就这样安慰自己了 前面是代码的实现,后面要做的只是把它放进QQ里而已。QQ是怎样的我不清楚,但基本上按照以下步骤可以把网页嵌进去。
首先,网页做好了,假设放在 C:\Communication 文件夹里。
接着,打开QQ的面板管理器(panel manager),如图:
点击添加面板(Add panel),这样就打开了一个网页,找到 QQ电台,如图:
点击上图的超链接,完成面板的添加。在QQ的安装目录下的找到你的Q号为目录名的目录(这里假设为123456),然后找到目录 PanelData ,打开文件 PanelData.ini,找到
userpanelver=7
iconName=radio.ico
iconUrl=http://portalinfo.qq.com/radio.ico
iconver=1
panelid=10003
userpanel=TRUE
url=http://fm.qq.com/player/index.shtml?clientuin=$uin$&clientkey=$key$
domainid=17000
PanelIndex=1005
type=0
tipsinfo=QQ电台
name=QQ电台
stream=1
bFlash=FALSE
bForbid=FALSE
修改成
userpanelver=7
iconName=radio.ico
iconUrl=http://portalinfo.qq.com/radio.ico
iconver=1
panelid=10003
userpanel=TRUE
url=file:///C:\Communication\Communication.htm
domainid=17000
PanelIndex=1005
type=0
tipsinfo=我的通信录
name=我的通信录
stream=0
bFlash=FALSE
bForbid=FALSE
重新登录QQ,看看QQ面板是否多了个图标,如果没有,面板管理器,把选项打上勾。
(完)
[ 本帖最后由 powerwind 于 2006-8-1 15:57 编辑 ] 要显示全部信息时不用JS写函数吧?XSL就是专门用来控制 XML 的格式显示。
Communication.xsl
<?xml version="1.0" encoding="gb2312"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head><title>test</title></head>
<body>
<table align="center" border="1">
<caption><strong>通信录</strong></caption>
<thead>
<th>姓名</th>
<th>性别</th>
<th>出生日期</th>
<th>住址</th>
<th>家里电话</th>
<th>手机号码</th>
<th>电子邮箱</th>
<th>QQ号码</th>
</thead>
<tbody>
<xsl:for-each select="//个人信息">
<tr>
<td><xsl:value-of select="姓名" /></td>
<td><xsl:apply-templates select="姓名"/></td>
<td><xsl:value-of select="出生日期" /></td>
<td><xsl:value-of select="住址" /></td>
<td><xsl:value-of select="家里电话" /></td>
<td><xsl:value-of select="手机号码" /></td>
<td><xsl:value-of select="电子邮箱" /></td>
<td><xsl:value-of select="QQ号码" /></td>
</tr>
</xsl:for-each>
</tbody>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="姓名">
<xsl:value-of select="@性别" />
</xsl:template>
</xsl:stylesheet>
然后修改 Communication.xml 文件一点点。
在 <?xml version="1.0" encoding="gb2312"?> 下一行加上 <?xml-stylesheet type="text/xsl" href="Communication.xsl"?>。用IE打开XML文件就可以看到格式化的输入了。
如果只想输入某类朋友的信息,比如只输出同学的信息。把 <xsl:for-each select="//个人信息">改成 <xsl:for-each select="通信录/同学/个人信息">即可。 原来此MJ非彼MJ…… 原帖由 powerwind 于 2006/8/1 00:51 发表
Wool 师兄说,会写程序的人很多都不会做界面的。呵呵~
所以界面做得不好就这样安慰自己了
你的界面估计会比hjack做得好看...哈哈...
我们公司的那个架构师做出来的界面那才叫丑... ps...楼主,,,是不是hjack给了你什么好处,,,你帮他们东家这么打广告...我现在每天上班都是免费在帮他们公司做产品测试... 原帖由 wool王 于 2006-8-2 00:03 发表
你的界面估计会比hjack做得好看...哈哈...
我们公司的那个架构师做出来的界面那才叫丑...
当然啦,根据你的理论(会写程序的不会做界面),我做的界面应该比hjack的好看。呵呵~
原帖由 wool王 于 2006-8-2 00:05 发表
ps...楼主,,,是不是hjack给了你什么好处,,,你帮他们东家这么打广告...我现在每天上班都是免费在帮他们公司做产品测试...
大家都在免费为他们公司测试,可这么久了,还是觉得QQ的反应很慢,输入法切换会出现假死现象。现在正式向hjack投诉。
发现对XML的验证方面没有说到,现在加上。
XML对格式有严格的要求,除了本身要求的每个元素以<>,要以</>(如果空元素可以这样: <Name/>),还可能定义验证文档,要求XML以指定格式设计。还是以 Communication.xml 为例,如果数据<姓名> 没有性别这个属性,而程序却去读取该属性,结果可想而知,又或者其中的个人信息的第一个子元素不是姓名,总之无顺序。这样会带来些不必要的麻烦。所以应该自定义它的格式。
Communication.dtd
<?xml version="1.0" encoding="GB2312"?>
<!ELEMENT 通信录 (同学,同事,其它朋友)>
<!ELEMENT 同学 (个人信息+)>
<!ELEMENT 同事 (个人信息+)>
<!ELEMENT 其它朋友 (个人信息+)>
<!ELEMENT 个人信息 (姓名,出生日期,住址,家里电话,手机号码,电子邮箱,QQ号码)>
<!ELEMENT 姓名 (#PCDATA)>
<!ELEMENT 出生日期 (#PCDATA)>
<!ELEMENT 住址 (#PCDATA)>
<!ELEMENT 家里电话 (#PCDATA)>
<!ELEMENT 手机号码 (#PCDATA)>
<!ELEMENT 电子邮箱 (#PCDATA)>
<!ELEMENT QQ号码 (#PCDATA)>
<!ATTLIST 姓名 性别 (男|女) "男" >
只要在 Communication.dtd文件中的 <?xml version="1.0" encoding="gb2312"?> 下一行加上<!DOCTYPE 通信录 SYSTEM "Communication.dtd">
<!ATTLIST 姓名 性别 (男|女) "男" >指定了 姓名 元素的属性 性别 默认值为男,可以删除Communication.dtd文件中所有 性别="男",而输出结果不变。
源码附件
[ 本帖最后由 powerwind 于 2006-8-6 16:02 编辑 ] 细看了楼主的文章。这个东西不错,能做出来骗MM,哈哈。。。我准备学这招。 原帖由 wool王 于 2006-8-2 14:06 发表
细看了楼主的文章。这个东西不错,能做出来骗MM,哈哈。。。我准备学这招。
楼上学习态度不端正,学习动机不良!
其实XML到处都在用,特别是JAVA的部署文件。很多程序的配置文件也是XML格式,千千静听的歌曲列表就是XML文件来的。很久前就接触过XML,可就是停在初级阶段。。。 上传了全部源码在15F 原帖由 wool王 于 2006-8-2 14:06 发表
细看了楼主的文章。这个东西不错,能做出来骗MM,哈哈。。。我准备学这招。
一齐学.哈哈:hug::victory:
PS:个附件好像有问题:time:
对不起,请不要从外部链接下载本论坛的附件。
PPT再看看吧. 有时候可以有时又不行,试试这个吧?
http://blog.gdutbbs.com/batch.download.php?aid=1977
如果不行,请到回收站下载吧,呵呵。
页:
[1]
2