工大后院

 找回密码
 加入后院

扫一扫,访问微社区

QQ登录

只需一步,快速开始

搜索
查看: 7446|回复: 22

JS+XML打造QQ个性通信录

[复制链接]
发表于 2006-7-31 12:40 | 显示全部楼层 |阅读模式
一接触XML就喜欢上它,当时还在本版发了叫JS+XML+HTML=?的帖,大概介绍用JS操纵XML实现查询功能做通信录。现在重写,把它嵌入到QQ面板,成为这样的效果:
发表于 2006-7-31 12:42 | 显示全部楼层
共享共享……
回复

使用道具 举报

 楼主| 发表于 2006-7-31 13:06 | 显示全部楼层
整个程序包括 Communication.htm,Communication.css,Communication.xml 三个主要文件和一些图片文件。
先介绍存放数据的文件 Communication.xml
XML全名是:eXtensible Markup Language(可扩展标识语言),它和网页超文本标记语言HTML有点相似。(不作详细介绍,有兴趣的可以搜索相关文章

假设你的朋友分为三类,分别是:同学,同事,其它朋友

所以XML数据文件可以为这样:
Communication.xml

  1. <?xml version="1.0" encoding="gb2312"?>
  2. <通信录>
  3.         <同学>
  4.                 <个人信息>
  5.                         <姓名 性别="男">陈一</姓名>
  6.                         <出生日期>1983-8</出生日期>
  7.                         <住址>湛江</住址>
  8.                         <家里电话>0729-3201928</家里电话>
  9.                         <手机号码>13756875467</手机号码>
  10.                         <电子邮箱>[email protected]</电子邮箱>
  11.                         <QQ号码>82521492</QQ号码>
  12.                 </个人信息>
  13.                 <个人信息>
  14.                         <姓名 性别="男">李二</姓名>
  15.                         <出生日期>1983-1-12</出生日期>
  16.                         <住址>汕头</住址>
  17.                         <家里电话>0750-2596329</家里电话>
  18.                         <手机号码>13637896451</手机号码>
  19.                         <电子邮箱>[email protected]</电子邮箱>
  20.                         <QQ号码>260117983</QQ号码>
  21.                 </个人信息>
  22.         </同学>
  23.         <同事>
  24.                 <个人信息>
  25.                         <姓名 性别="女">王三</姓名>
  26.                         <出生日期>1986-5-6</出生日期>
  27.                         <住址>广州市</住址>
  28.                         <家里电话>020-88158546</家里电话>
  29.                         <手机号码>1392585676</手机号码>
  30.                         <电子邮箱>[email protected]</电子邮箱>
  31.                         <QQ号码>7454652657</QQ号码>
  32.                 </个人信息>
  33.                 <个人信息>
  34.                         <姓名 性别="女">何四</姓名>
  35.                         <出生日期> 1985-2-5</出生日期>
  36.                         <住址>北京</住址>
  37.                         <家里电话>010-88816594</家里电话>
  38.                         <手机号码>13512586555</手机号码>
  39.                         <电子邮箱>[email protected]</电子邮箱>
  40.                         <QQ号码>764354985</QQ号码>
  41.                 </个人信息>
  42.         </同事>
  43.         <其它朋友>
  44.                 <个人信息>
  45.                         <姓名 性别="男">陈四</姓名>
  46.                         <出生日期>1983-5-23</出生日期>
  47.                         <住址>电白</住址>
  48.                         <家里电话>0714-85654685</家里电话>
  49.                         <手机号码>13929634673</手机号码>
  50.                         <电子邮箱>[email protected]</电子邮箱>
  51.                         <QQ号码>2824368488</QQ号码>
  52.                 </个人信息>
  53.                 <个人信息>
  54.                         <姓名 性别="男">何时</姓名>
  55.                         <出生日期>1986-6-3</出生日期>
  56.                         <住址>广州</住址>
  57.                         <家里电话>020-87685456</家里电话>
  58.                         <手机号码>13752856285</手机号码>
  59.                         <电子邮箱>[email protected]</电子邮箱>
  60.                         <QQ号码>423719510</QQ号码>
  61.                 </个人信息>
  62.         </其它朋友>
  63. </通信录>
复制代码

上面的XML文档可以理解成这样的树形结构:
22.JPG
其中元素个人信息的子元素没有画出,其子元素分别是:姓名,出生日期,住址,家里电话,手机号码,电子邮箱,QQ号码。这几个元素都没有子元素,而只是有值(其中姓名还有一个属性—性别)。

因为用JS操纵XML时是采用DOM文档对象模型,所以要先知道这个文档的结构。

[ 本帖最后由 powerwind 于 2006-8-6 13:17 编辑 ]
回复

使用道具 举报

 楼主| 发表于 2006-7-31 16:22 | 显示全部楼层
限于篇幅,略去外观的设计,也就是略去CSS样式文件 Communication.css 现在就只剩下 Communication.htmCommunication.js 两个文件了。

因此,只给出重要代码

Communication.htm

这里应该是htm(已改了,PPT应该没意见吧……)
                                                        ---MODIFY  BY  iptton


  1. <html>
  2. <head>
  3.     <link href="Communication.css" type="text/css" rel="stylesheet" />
  4.     <script language="javascript" src="Communication.js"></script>
  5. </head>
  6. <body>
  7.         <table><tr><td>
  8.         <input id="inputText" type="text" onmouseover="this.focus()" onfocus="this.select()" value="请输入关键字查询" />
  9.         </td></tr>

  10.         <tr><td width="174">
  11.                 <select id="styles">
  12.                         <option value="Name" selected>姓名
  13.                         <option value="FamilyName">姓氏
  14.                         <option value="Cellphone">手机号码
  15.                         <option value="QQ">QQ号码
  16.         </select>
  17.                         &nbsp;
  18.         <input type="image" src="search_btn.gif" style="cursor:hand" onclick="find(styles.value,inputText.value)" />
  19.         </td></tr>  
  20.                  
  21.           <tr><td>
  22.                 <select id="classes">
  23.             <option value="all" selected>全部
  24.             <option value="classmate">同学
  25.             <option value="workmate">同事
  26.             <option value="others">其它朋友
  27.         </select>
  28.                         &nbsp;
  29.         <a href="javascript:seeAll(classes.value)">查看</a>
  30.         </td></tr>
  31. </table>
  32. </body>
  33. </html>
复制代码

[ 本帖最后由 iptton 于 2006-8-17 19:38 编辑 ]
回复

使用道具 举报

 楼主| 发表于 2006-7-31 16:36 | 显示全部楼层
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[0].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[0].value+"</td>";
                        else result+="<td>"+currentNode.text+"</td>";
                }
                result+="</tr><tr>";
        }
        return result;
}

这样,就基本上完成了一个网页了。至于如何嵌入QQ面板,==

[ 本帖最后由 powerwind 于 2006-8-1 15:57 编辑 ]
回复

使用道具 举报

发表于 2006-7-31 22:45 | 显示全部楼层
很有创意的原创内容.加精了...

PS...楼主别不好意思,别因为是自己的文章就不敢加精.写得好就要让大家都知道...
回复

使用道具 举报

 楼主| 发表于 2006-7-31 22:49 | 显示全部楼层
楼上的,我还没有写完呢!呵呵~
待续。。。
回复

使用道具 举报

发表于 2006-8-1 00:37 | 显示全部楼层
说真的……
POWERWIND师兄的界面做得不怎么样……
跟偶的水平无甚差距……

当然,后面的代码实现……[em021]
回复

使用道具 举报

 楼主| 发表于 2006-8-1 00:51 | 显示全部楼层
原帖由 iptton 于 2006-8-1 00:37 发表
说真的……
POWERWIND师兄的界面做得不怎么样……
跟偶的水平无甚差距……

当然,后面的代码实现……


Wool 师兄说,会写程序的人很多都不会做界面的。呵呵~

所以界面做得不好就这样安慰自己了
回复

使用道具 举报

 楼主| 发表于 2006-8-1 01:13 | 显示全部楼层
前面是代码的实现,后面要做的只是把它放进QQ里而已。QQ是怎样的我不清楚,但基本上按照以下步骤可以把网页嵌进去。
首先,网页做好了,假设放在 C:\Communication 文件夹里。
接着,打开QQ的面板管理器(panel manager),如图:
1.JPG
点击  添加面板(Add panel),这样就打开了一个网页,找到 QQ电台,如图:
2.JPG
点击上图的超链接,完成面板的添加。在QQ的安装目录下的找到你的Q号为目录名的目录(这里假设为123456),然后找到目录 PanelData ,打开文件 PanelData.ini,找到
[10003]
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

修改成
[10003]
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 编辑 ]
回复

使用道具 举报

发表于 2006-8-1 15:55 | 显示全部楼层
要显示全部信息时不用JS写函数吧?XSL就是专门用来控制 XML 的格式显示。

Communication.xsl

  1. <?xml version="1.0" encoding="gb2312"?>
  2. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  3.         <xsl:template match="/">
  4.                 <html>
  5.                 <head><title>test</title></head>
  6.                 <body>
  7.                 <table align="center" border="1">
  8.                 <caption><strong>通信录</strong></caption>
  9.                 <thead>
  10.                         <th>姓名</th>
  11.                         <th>性别</th>
  12.                         <th>出生日期</th>
  13.                         <th>住址</th>
  14.                         <th>家里电话</th>
  15.                         <th>手机号码</th>
  16.                         <th>电子邮箱</th>
  17.                         <th>QQ号码</th>
  18.                 </thead>
  19.                 <tbody>
  20.                 <xsl:for-each select="//个人信息">
  21.                 <tr>
  22.                         <td><xsl:value-of select="姓名" /></td>
  23.                         <td><xsl:apply-templates select="姓名"/></td>
  24.                         <td><xsl:value-of select="出生日期" /></td>
  25.                         <td><xsl:value-of select="住址" /></td>
  26.                         <td><xsl:value-of select="家里电话" /></td>
  27.                         <td><xsl:value-of select="手机号码" /></td>
  28.                         <td><xsl:value-of select="电子邮箱" /></td>
  29.                         <td><xsl:value-of select="QQ号码" /></td>
  30.                 </tr>
  31.                 </xsl:for-each>
  32.                 </tbody>
  33.                 </table>
  34.                 </body>
  35.                 </html>
  36.         </xsl:template>

  37.         <xsl:template match="姓名">
  38.         <xsl:value-of select="@性别" />
  39.         </xsl:template>
  40. </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="通信录/同学/个人信息">即可。
回复

使用道具 举报

发表于 2006-8-1 17:34 | 显示全部楼层
原来此MJ非彼MJ……
回复

使用道具 举报

发表于 2006-8-2 00:03 | 显示全部楼层
原帖由 powerwind 于 2006/8/1 00:51 发表


Wool 师兄说,会写程序的人很多都不会做界面的。呵呵~

所以界面做得不好就这样安慰自己了



你的界面估计会比hjack做得好看...哈哈...

我们公司的那个架构师做出来的界面那才叫丑...
回复

使用道具 举报

发表于 2006-8-2 00:05 | 显示全部楼层
ps...楼主,,,是不是hjack给了你什么好处,,,你帮他们东家这么打广告...我现在每天上班都是免费在帮他们公司做产品测试...
回复

使用道具 举报

 楼主| 发表于 2006-8-2 11:20 | 显示全部楼层
原帖由 wool王 于 2006-8-2 00:03 发表
你的界面估计会比hjack做得好看...哈哈...
我们公司的那个架构师做出来的界面那才叫丑...


当然啦,根据你的理论(会写程序的不会做界面),我做的界面应该比hjack的好看。呵呵~


[quote]原帖由 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 编辑 ]
回复

使用道具 举报

发表于 2006-8-2 14:06 | 显示全部楼层
细看了楼主的文章。这个东西不错,能做出来骗MM,哈哈。。。我准备学这招。
回复

使用道具 举报

 楼主| 发表于 2006-8-2 15:17 | 显示全部楼层
原帖由 wool王 于 2006-8-2 14:06 发表
细看了楼主的文章。这个东西不错,能做出来骗MM,哈哈。。。我准备学这招。


楼上学习态度不端正,学习动机不良!

其实XML到处都在用,特别是JAVA的部署文件。很多程序的配置文件也是XML格式,千千静听的歌曲列表就是XML文件来的。很久前就接触过XML,可就是停在初级阶段。。。
回复

使用道具 举报

 楼主| 发表于 2006-8-6 13:21 | 显示全部楼层
上传了全部源码在15F
回复

使用道具 举报

发表于 2006-8-8 22:18 | 显示全部楼层
原帖由 wool王 于 2006-8-2 14:06 发表
细看了楼主的文章。这个东西不错,能做出来骗MM,哈哈。。。我准备学这招。


一齐学.哈哈:hug::victory:

PS:个附件好像有问题:time:

对不起,请不要从外部链接下载本论坛的附件。

PPT再看看吧.
回复

使用道具 举报

 楼主| 发表于 2006-8-8 22:25 | 显示全部楼层
有时候可以有时又不行,试试这个吧?
http://blog.gdutbbs.com/batch.download.php?aid=1977
如果不行,请到回收站下载吧,呵呵。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入后院

本版积分规则

QQ|Archiver|手机版|小黑屋|广告业务Q|工大后院 ( 粤ICP备10013660号 )

GMT+8, 2024-5-1 04:59

Powered by Discuz! X3.5

Copyright © 2001-2024 Tencent Cloud.

快速回复 返回顶部 返回列表