老赵点滴


  先做人,再做技术人员,最后做程序员。
  我的理想:“让外国人看中国人写的技术书籍和文章”。Try as I might
posts - 287, comments - 10552, trackbacks - 137, articles - 6
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

Live Messenger对话框

  时常在某些朋友的blog中看到一个可供聊天的对话框,它能让正在浏览这个站点的用户进行聊天。不过在我看来,这个功能形同鸡肋——谁会知道哪些人正在浏览,又有哪些人可以聊天呢?不过今天在浏览LoveCherry的blog时发现在左侧边栏里出现了一个可供聊天的Live Messenger对话框,顿时让我产生了兴趣。不过知道这个东东的人似乎还不多,因此只能动用搜索引擎了(在这里想再说一句多余的话,因为我时常会收到一些类似于“ASP.NET AJAX框架哪里可以下载”之类的问题,所以我建议那些朋友一定要养成先搜再问的习惯)。那么我们就先来看看这个东西具体是什么样的吧。

  首先,我们可以访问这个页面(http://settings.messenger.live.com/applications/CreateHtml.aspx),从中可以看出微软提供了两种方式供用户使用Live Messenger的Web聊天功能。

  • 提供一个链接(),点击它则会弹出一个页面可供聊天——于是别人就可以通过这个页面与您联系了。值得一提的是,图标也会根据用户当时的状态不同而改变。
  • 提供了一段代码,在页面上直接放入一块较小的区域显示聊天页面。很显然,这是一个iframe。

  在进行了简单的试验(使用Web Live Messenger和自己的Live Messenger聊天)之后,发现这个小玩意儿的功能还是比较可圈可点的。

  • 可以选择是否允许匿名用户使用Web Live Messenger(http://settings.messenger.live.com/applications/WebSettings.aspx)。
  • 性能很不错,基本上没有明显延迟,当然这可能和用户本身的网络条件有关。
  • 聊天的体验比想象中高很多,我们可以在Web Live Messenger的界面上发现“最近一条信息收于XXXX年X月X日 XX:XX:XX”以及“XXXX正在输入消息”的字样。此外,我们聊天中使用的特殊字体和表情符号也能正确显示。
  • 我尝试通过Web Live Messenger找出对方的IM帐号,但似乎它对于这点有着很好的保护,这意味着如果用户将Web Live Messenger放在blog上,可以避免因为泄露Email地址而遭受垃圾邮件地攻击。

  试验了之后,我决定将其放在我的blog中,不过到底该怎么放呢?

Live Demo

  现在访问LoveCherry的blog会发现他已经将Web Live Messenger从边栏撤下了。边栏实在太窄,如果使用一个稍微长一些的Nick就会被顶的很高,而且由于一行能显示的文字太少,用户体验也很差。最后,我使用了“传统”网页内嵌聊天对话框的做法。如果您现在正在浏览我的blog,就会发现页面的右下角出现了一个矩形的Windows Live Messenger的图片,点击它则会显示出一个300*400的Web Live Messenger聊天对话框。如果您觉得这个对话框挡着页面上的内容了,就可以点击对话框左上角的关闭按钮,这样页面上又只剩下了右下角的矩形图片了。同时,我选择了淡入淡出的效果来显示/隐藏Web Live Messenger聊天对话框。这么做的目的只有一个,那就是让用户体验更酷一些。:)

  现在大家可以试验一下Web Live Messenger的聊天功能了。不过请大家能够访问http://settings.messenger.live.com/applications/CreateHtml.aspx,在页面中和自己的Live Messenger进行聊天。如果您直接在我的blog上测试Web Live Messenger,我实在会忙不过来。:(

实现

  实现并不复杂,我总共用了大约2个小时,其中还包括学习了一些jQuery的功能所花的时间。唉,没想到我居然到现在才第一次使用这个如此了得的JavaScript框架。不得不说,如果您正在寻找一款方便您开发前端应用程序的JavaScript框架,并且希望它足够的小,那么jQuery很可能就是您需要的。与它强大的功能不相称的是迷你的体积。一个经过混淆,还没有Gzip压缩的jQuery脚本文件才26K大小,但是它带给你的便利可以帮您节省大量的工作。

  那么我们现在就开始吧,首先,我们需要让Web Live Messenger的聊天对话框能够永远显示在页面的可视范围之内。要实现这个功能,关键还是在于对页面中元素尺寸的计算。请看如下代码:

<script language="javascript" type="text/javascript">
    function getClientBounds()
    {
        var clientWidth;
        var clientHeight;
       
        if ($.browser.msie)
        {
            clientWidth = document.body.clientWidth;
            clientHeight = document.body.clientHeight;
        }
        else if ($.browser.safari)
        {
            clientWidth = window.innerWidth;
            clientHeight = window.innerHeight;
        }
        else if ($.browser.opera)
        {
            clientWidth = Math.min(window.innerWidth,
                document.body.clientWidth);
            clientHeight = Math.min(window.innerHeight,
                document.body.clientHeight);
        }
        else
        {
            clientWidth = Math.min(window.innerWidth,
                document.documentElement.clientWidth);
            clientHeight = Math.min(window.innerHeight,
                document.documentElement.clientHeight);
        }
 
        return { width : clientWidth, height : clientHeight };
    }
 
    function resetLiveMessengerPosition()
    {
        var clientBounds = getClientBounds();
        var container = document.getElementById("liveMessengerContainer");
       
        var scrollLeft = (document.documentElement.scrollLeft ?
            document.documentElement.scrollLeft : document.body.scrollLeft);
        var scrollTop = (document.documentElement.scrollTop ?
            document.documentElement.scrollTop : document.body.scrollTop);
               
        var containerLeft = scrollLeft + clientBounds.width -
            container.clientWidth – 5;
        var containerTop = scrollTop + clientBounds.height -
            container.clientHeight;
               
        $("#liveMessengerContainer").css(
            {top : containerTop + "px", left : containerLeft + "px"});
    }
<script>

  以上getClientBounds方法通过判断浏览器类型来得到页面显示区域的精确尺寸,而resetLiveMessengerPosition方法根据liveMessengerContainer元素的尺寸重设该容器在浏览器中的位置。这两个方法谈不上“技术”,而更像是一种“经验”,它们都是我属于所收藏的JavaScript代码,如果大家需要的话也可以保留,或者需要时再来我的blog查找(其实我以前也有文章用到过这些方法)。需要注意的是,如果您使用了的是IE浏览器,在某些的页面上可能会需要通过document.documentElement.clientWidth来获得代码(clientHeight也一样),具体原因我正在调查,大家在使用时也请注意这点。

  哎?那么resetLiveMessengerPosition方法该在什么时候调用呢?先不着急,我们再来实现Web Live Messenger的显示/隐藏,以及淡入淡出效果——为什么放在一起实现了?因为我们用到了jQuery框架。请看如下代码:

<div id="liveMessengerContainer" style="position:absolute;">
    <div style="border: solid 1px black; width:160;
         height: 39px; cursor:pointer;
         background-image:url(Messenger_Header_bg.gif)"
         id="liveMessengerThumb">
        <img src="Messenger_logo_beta.gif"
             alt="
使用Live Messenger联系我"
             style="margin: 10px 10px 0px 9px;"/>
    </div>
    <table border="0" cellpadding="0" cellspacing="0"
           id="liveMessengerPanel">
        <tr>
            <td valign="top">
                <img id="hideLiveMessengerPanel"
                     style="cursor:pointer; margin-right: 3px;"
                     src="Messenger_close_sm.gif" alt="
关闭" />
            </td>
            <td>
                <iframe
                    src="..." width="300" frameborder="0"
                    style="border: solid 1px black; width: 300px;
                    height: 400px;"></iframe>
            </td>
        </tr>
    </table>
<div>

<script language="javascript" type="text/javascript">
    $("#liveMessengerPanel").hide();
   
    $(document).ready(function(){
        $(window).scroll(resetLiveMessengerPosition);
        $(window).resize(resetLiveMessengerPosition);
   
        resetLiveMessengerPosition();
       
        $("#liveMessengerThumb").click(function(){
            $("#liveMessengerThumb").fadeOut(500, function(){
                $("#liveMessengerPanel").fadeIn(500, function(){
                    resetLiveMessengerPosition();
                });
                resetLiveMessengerPosition();
            });
        });
       
        $("#hideLiveMessengerPanel").click(function(){
            $("#liveMessengerPanel").fadeOut(500, function(){
                $("#liveMessengerThumb").fadeIn(500, function(){
                    resetLiveMessengerPosition();
                });
                resetLiveMessengerPosition();
            });
        });
    });
<script>

  liveMessengerContainer容器中的内容我就不进行太多解释了。同样略过的还有jQuery的基本使用,不过相信有一定JavaScript基础的朋友也能比较轻松地看懂。以上JavaScript代码的第一句隐藏了聊天对话框,接着在jQuery中经典的$(document).ready事件中对以有的元素进行操作。首先,我们要求在用户移动了滚动条(scroll),或者改变了浏览器大小(resize)时重新设置容器的位置。需要注意的是,我们接着需要显式调用resetLiveMessengerPosition方法来对容器的位置进行初始化。然后jQuery开始展现了它的神奇之处,短短几行代码即完成了淡入淡出的切换功能,让人叹为观止。

  至此,在页面中嵌入一个Web Live Messenger的工作就完成了。欢迎大家提出意见和建议,帮助我改进这个功能。

Feedback

#1楼    回复  引用  查看    

2007-11-10 00:49 by 红茶TT      
好东西

#2楼 [楼主]   回复  引用  查看    

2007-11-10 00:56 by Jeffrey Zhao      
已经有不少朋友试着玩儿了,呵呵。不过建议还是自己和自己玩比较好。:)

#3楼    回复  引用  查看    

2007-11-10 08:25 by 天生俪姿      
一个字 酷~!
感觉比 QQ的要好!
不过好像我上下翻网页的时候 那个 就没有了!
个人 觉得可以和 Asp.netAJax 的Tookit 的 那个 什么Panel 结合一下可以吧!
记下来 有空研究
收藏中。。

#4楼    回复  引用  查看    

2007-11-10 09:31 by 丹心猪(Dansinge)      
mark,日后观注

#5楼    回复  引用  查看    

2007-11-10 10:00 by Enzo      
it is funny

#6楼    回复  引用  查看    

2007-11-10 10:13 by Zhuang miao      
真钻研~~

#7楼    回复  引用  查看    

2007-11-10 10:39 by 坐断东南 笑煞之!!      
一个字 酷。

#8楼    回复  引用  查看    

2007-11-10 10:44 by Zhuang miao      
刚刚在asp。net首页上发现了一篇介绍这个的文章
http://www.nikhilk.net/Entry.aspx?id=179

#9楼    回复  引用  查看    

2007-11-10 10:58 by Cat Chen      
应该能够将你的站内连接替换为顶层iframe内打开,这样无论如何那个Messenger都不会被刷走了。

#10楼    回复  引用    

2007-11-10 11:15 by 老A [未注册用户]
@Cat Chen
馊主意,不好控制的说,链接都是指向你的页面还好说,如果是链接到别人的博客、网站,还留着你的Messenger button?

#11楼    回复  引用    

2007-11-10 11:20 by 老A [未注册用户]
给老赵补充个建议:
那个image button 改为纵向,放到页面左下角。
道理不用我说,你明白。

#12楼    回复  引用  查看    

2007-11-10 12:45 by Lostinet      
Cool
我们也打算做这样的互动功能.
不过实在想不到如何解决cookie被拦截的问题.

#13楼 [楼主]   回复  引用  查看    

2007-11-10 13:04 by Jeffrey Zhao      
@Cat Chen
嗯?没理解你的意思。

#14楼 [楼主]   回复  引用  查看    

2007-11-10 13:05 by Jeffrey Zhao      
@Lostinet
具体说说?不过我想微软这个肯定没有什么低级的安全性问题。

#15楼 [楼主]   回复  引用  查看    

2007-11-10 13:07 by Jeffrey Zhao      
@天生俪姿
AlwaysVisiblePanel?的确可以,不过这里没有asp.net ajax环境(其实是文章页有,但是首页之类的就没有了,不容易控制),所以就没有用。而且如果小功能用AjaxControlTookit反而会有点适得其反的感觉,太大。

#16楼    回复  引用  查看    

2007-11-10 13:25 by Lostinet      
我说的拦截指的是浏览器的行为.

当在cnblogs.com上引用其他网站的资源时, 那么该网站就不能取得用户登录信息.

这样,在页面中包含其他网站的通信, cookie功能就会受限制.

#17楼    回复  引用  查看    

2007-11-10 13:27 by pk的眼泪      
有个bug
滚动条能无限止的滚动...

#18楼    回复  引用  查看    

2007-11-10 13:42 by MK2      
老赵的高亮代码段有问题, 结束标记错了...

呵呵, 测试成功...

#19楼    回复  引用  查看    

2007-11-10 13:44 by ξσ Dicky σξ      
Good,已借用到偶的Blog,呵呵,谢谢咯。。。

#20楼 [楼主]   回复  引用  查看    

2007-11-10 14:56 by Jeffrey Zhao      
@老A
没有纵向的图片,呵呵。

#21楼 [楼主]   回复  引用  查看    

2007-11-10 14:57 by Jeffrey Zhao      
@Lostinet
没听懂,不过这个应该是安全性方面的限制,呵呵。

#22楼 [楼主]   回复  引用  查看    

2007-11-10 14:57 by Jeffrey Zhao      
@pk的眼泪
我没有发现,能具体说一下重现的方式吗?

#23楼    回复  引用  查看    

2007-11-10 16:51 by ∈鱼杆      
@Jeffrey Zhao


--引用--------------------------------------------------
如果您使用了的是IE浏览器,在某些的页面上可能会需要通过document.documentElement.clientWidth来获得代码(clientHeight也一样),具体原因我正在调查,大家在使用时也请注意这点。
--------------------------------------------------------

关于这个问题,是因为网页中引用了“文档标准声明”造成的 即<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
。当文档有了标准声明时, document.body.clientWidth 在网页内容不满一屏幕时,取值就会不准确。
解决方法:
当文档有了标准声明时document.compatMode 的值就等于 "CSS1compat", 因此, 我们可以根据 document.compatMode 的值来判断文档是否加了标准声明。有文档声明就调用
document.documentElement.clientWidth方法

Javascript方法:
var width = document.compatMode=="CSS1Compat" ? document.documentElement.clientWidth : document.body.clientWidth;

简单的说明一下,如果要获得真实的具体高度和宽度,还需要判断一下ScrollHeight,ScrollWidth



#24楼 [楼主]   回复  引用  查看    

2007-11-10 18:53 by Jeffrey Zhao      
@∈鱼杆
万分感谢。:)

#25楼    回复  引用  查看    

2007-11-11 00:29 by volnet(可以叫我大V)      
刚刚在开心就好的网页里看到这个,结果不知道哪里调用到MS的这个服务……哈哈,这里原来就有,真是缘分啊

#26楼    回复  引用  查看    

2007-11-11 08:46 by Cat Chen      
@老A
我没有说改变所有链接的行为啊,我只是说改变本站站内链接(即jeffreyzhao.cnblogs.com或www.cnblogs.com/jeffreyzhao开头的)的行为啊。

#27楼    回复  引用  查看    

2007-11-11 08:47 by Cat Chen      
@Jeffrey Zhao
也就是说,你通过脚本,使得所有站内链接都在iframe里打开,该iframe覆盖在当前页面上。

#28楼    回复  引用  查看    

2007-11-11 08:51 by Cat Chen      
@∈鱼杆
确实是这样的,在standards mode下面,<body />是display:inline的元素,因此没有固定的height也不能设置固定的height,其height只能根据内容大小而变化,不再像以前一样代表浏览器显示区域大小,因此要改为从documentElement获取height。

#29楼    回复  引用  查看    

2007-11-11 09:31 by jillzhang      
ms官方主页上也出现这个东东的连接了

#30楼 [楼主]   回复  引用  查看    

2007-11-11 16:42 by Jeffrey Zhao      
@Cat Chen
这个问题还是比较大的,最简单的就是bookmark又失效了。

#31楼    回复  引用    

2007-11-11 19:17 by Linxi [未注册用户]
老赵瘦了,不要太劳累。身体是第一位的。

#32楼    回复  引用  查看    

2007-11-11 19:57 by volnet(可以叫我大V)      
TrackBack

博客园会自己发这个哦,强了……,我都不知道,呵呵

#33楼    回复  引用  查看    

2007-11-11 21:59 by 心有灵犀      
jQuery是个非常非常好的东东啊

#34楼 [楼主]   回复  引用  查看    

2007-11-11 22:35 by Jeffrey Zhao      
@Linxi
这张是2年多前的照片,老赵现在奇胖无比。

#35楼 [楼主]   回复  引用  查看    

2007-11-11 23:52 by Jeffrey Zhao      
@volnet(可以叫我大V)
恩……基本上blog都有了。

#36楼    回复  引用  查看    

2007-11-12 09:34 by Clark Zheng      
老赵真的很帅!

#37楼 [楼主]   回复  引用  查看    

2007-11-12 11:23 by Jeffrey Zhao      
@Clark Zheng
我其实又胖又丑的,从来没有mm向我表白过,嗯。
我也又胖又丑,不过博主照片看起来蛮帅啊

#39楼 [楼主]   回复  引用  查看    

2007-11-12 14:28 by Jeffrey Zhao      
三年前,也就是体重轻30公斤的时候。

#40楼    回复  引用  查看    

2007-11-12 19:32 by Zhuang miao      
啊?3年你长了30公斤??

#41楼 [楼主]   回复  引用  查看    

2007-11-12 21:54 by Jeffrey Zhao      
@Zhuang miao
很牛吧

#42楼    回复  引用  查看    

2007-11-12 23:07 by Zhuang miao      
一项很NB的生物工程

#43楼    回复  引用  查看    

2007-11-12 23:07 by Zhuang miao      
;-)

#44楼    回复  引用  查看    

2007-11-12 23:08 by Zhuang miao      
老赵注意身体啊!多锻炼

#45楼 [楼主]   回复  引用  查看    

2007-11-12 23:10 by Jeffrey Zhao      
@Zhuang miao
锻炼过,没有效果,而且我其实平时休息很少,估计是内分泌紊乱了。

#46楼    回复  引用    

2007-11-13 10:09 by blank3 [未注册用户]
赞一个

#47楼    回复  引用  查看    

2007-11-13 20:24 by 周行天下      
去掉这个东西吧,网页速度变慢了。

#48楼 [楼主]   回复  引用  查看    

2007-11-13 20:25 by Jeffrey Zhao      
@周行天下
加在页面最底部的,不会内容显示速度的。

#49楼    回复  引用  查看    

2007-11-14 11:32 by 杨正祎      
以前我倾向于prototype,不过,现在我更倾向于jQuery。今天看到一个mac菜单,用jQuery做的,一个字——华丽!

#50楼    回复  引用  查看    

2007-11-15 15:04 by MK2      
@Jeffrey Zhao
记得高考前, 110多, 然后现在才大4.....150多....不过你三年长30KG....的确难得..

#51楼    回复  引用  查看    

2007-11-15 15:05 by MK2      
@杨正祎
interface?

#52楼 [楼主]   回复  引用  查看    

2007-11-15 15:19 by Jeffrey Zhao      
@MK2
你也够厉害了。

#53楼    回复  引用  查看    

2007-11-17 11:18 by 哥哥.Net      
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


加了这句之后,只显示一下下就消失了。:)

#54楼 [楼主]   回复  引用  查看    

2007-11-17 12:41 by Jeffrey Zhao      
@哥哥.Net
请查看上面的一个关于显示区域尺寸计算方法的文章.

#55楼    回复  引用  查看    

2007-11-20 12:45 by Yoshow      
这个东西 酷啊..

#56楼    回复  引用  查看    

2007-11-20 22:46 by RookieStar      
不错,mark一记~~

#57楼    回复  引用  查看    

2007-11-21 16:57 by 浪子      
--引用--------------------------------------------------
Cat Chen: @Jeffrey Zhao
也就是说,你通过脚本,使得所有站内链接都在iframe里打开,该iframe覆盖在当前页面上。
--------------------------------------------------------

我比较狠一点,直接新开窗体,嘿嘿,就不怕跳转了

#58楼    回复  引用  查看    

2007-11-21 17:58 by ColdDog      
mark,晚上回去试试~

#59楼    回复  引用  查看    

2007-11-25 11:08 by Michael Wang      
能加到live space里面吗?

#60楼 [楼主]   回复  引用  查看    

2007-11-25 14:41 by Jeffrey Zhao      
@Michael Wang
似乎可以,不妨一试。

#61楼    回复  引用  查看    

2007-12-18 12:35 by 任清晓(NET)      
在哪添加上面的代码啊

#62楼 [楼主]   回复  引用  查看    

2007-12-18 14:32 by Jeffrey Zhao      
@任清晓(NET)
我真的不知道哪里没有说清楚了,呵呵。

#63楼    回复  引用  查看    

2007-12-18 17:00 by 任清晓(NET)      
代码说的非常清楚。我想问下如果我要把这个功能也放到cnblog上,进入“管理”后,我就不知道把代码放哪了,呵呵!麻烦老赵了。

#64楼    回复  引用  查看    

2007-12-22 14:48 by 松杰      
script的结束符号少了“/"
"var containerLeft = scrollLeft + clientBounds.width -
container.clientWidth – 5;"中有个“-”号格式不对。

#65楼 [楼主]   回复  引用  查看    

2007-12-22 15:55 by Jeffrey Zhao      
--引用--------------------------------------------------
任清晓(NET): 代码说的非常清楚。我想问下如果我要把这个功能也放到cnblog上,进入“管理”后,我就不知道把代码放哪了,呵呵!麻烦老赵了。
--------------------------------------------------------
博客园的设置里吧

#66楼 [楼主]   回复  引用  查看    

2007-12-22 16:03 by Jeffrey Zhao      
@松杰
换了种编辑代码的方式,一开始不太熟练。:)

#67楼    回复  引用  查看    

2008-01-04 13:16 by 马可香蕉      
准备好好学习下几个JS库

#68楼    回复  引用  查看    

2008-01-05 20:03 by Argo      
成功,讲的非常清楚。

#69楼    回复  引用