转:http://doublechou.us/wordpress-google-wave-style-comment-with-jquery-part-1/

Google Wave已经内测好长时间了,@lookon大叔的提名接力似乎也排到了七八千咯。苏有幸在一个月前得到@Cattyhouse叔叔的邀请一枚,算是赶在第二梯队的尾巴上体验了一把Google Wave。页面和Gnome差不多,比较Q。

但是苏对它的评价并不是很高:一,帖子少;二,任何人都能改东西,总有那么一两个不自觉的; 三,无法退出一个Wave,一旦有那个不长眼的加个机器人,后果不堪设想;四,无法删除一个Wave,Trash里面全是Muted的空Wave。

其中第二三四都是Google Wave的设计理念导致的。老外和我们的想法很不同,他们一定觉得Wave作为一个协作系统和讨论平台是不应该出现”admin”这种东西的,而且作为一 个项目不能说退出就退出。他们认为Wave一旦发出,就至少有两个人,所以不应该让你删除的Wave影响其他人;一旦加入一个讨论,自己肯定不能退,无论 你是因为工作还是爱好,一旦加入就代表有责任有兴趣参与讨论,而没考虑你无辜的情况。而没有admin,也就不可能把你清出去;Wave的卖点就是大家可 以在一张纸上同时画画,所以你的东西不让改那什么都无从谈起了。总结一下就是“强买强卖”+“一锤子买卖”。

苏觉得至少可以这么改进: 1, 公共Wave不可删除,私人的可以;2, 任何空Wave都可以删除;3,可以离场或经其他所有人投票后可以离场(用于清理不自觉的和不长眼的);4,插入机器人要所有人投票通过,如果可以自己离 场此条作废; 修改应发送修改请求,或修改结果要经“编辑链”的“上游”通过(表达不太清楚,用jQuery的写法就是prev()而不是prevAll(); ); 5, 所有修改结果都像pastebin一样有存档,有据可查。这样Wave才能算作一个有秩序的协作系统和讨论平台,才会真正有企业对它感兴趣,其实企业最需 要的不是实时,再实时有视频会议说的清楚么?企业最需要的是秩序,现在的Wave最多算个会议的白板,不能主导会议的方式。

好吧,苏作为一个TMT分析员已经跑题了,不谈工作不谈工作。下面开始苏的“WordPress瞎搞教程“,老鸟可以扫过,但请别飘过,毕竟苏的brandwidth不是特供你飘来飘去滴,苏希望物尽其用,你不想说话可以潜水,但别跳出来说没用的。

我的出发点和@lookon叔叔不一样,他是在想怎么把Wave引入博客,我是想怎么把博客变成Wave。本着中国的“大山寨”精神,我没有,还不行自个儿造么。。。

先上一张Google Wave的单个Wave截图:

这张是苏和推特美女@sdelayang的私人ping哦,相信大家在直勾勾滴盯着美女照片看的同时脖子扭扭屁股扭扭滴也能发现Google Wave的New Wave主要(细节苏会在以后的文章中一点一点纠结出来)有如下特征:

1,嵌套; 2,未读消息前面显示一个小绿条; 3,作者头像右下角有一个小绿点;4,每条消息之间用点线分开;5,嵌套评论有阴影。还有2个截不出来的特征: 6,鼠标放在消息下方会有一个蓝色圆框出来让你继续嵌套或者是续接这个嵌套层,如下图; 7, 鼠标左键点击消息会出现一个绿色框选中该条消息,继续单击无法取消,只能点击别的消息或者离开该Wave,效果才会消失(也就是说你要么不点,一旦开始点 就始终会有一个绿色的框框在某条消息上。)。单击过的消息前面的小绿条消失。

也就是说,你的WordPress评论只要有如下特征,就基本可以伪装成小半个Google Wave了。

下面纠结实现方法:

其中1,嵌套是WordPress 2.7以后就自带的,本身已经非常强大,不去管它;

4, 每条消息之间用点线分开,这个最简单,css的问题。以下均以WordPress 2.8.4的default主题的comments.php里面的class为例,当然default是用的<?php wp_list_comments(); ?>这个函数,肉眼看不到任何class,但不要忘记我们还有Firebug这个强大的debug工具 :-) 只需要

[class~=vcard] {padding-top: 5px; border-top: 1px dotted gray; }

就可以了。||注释: [class~=vcard],css高级选择器,意思是有class=”1 2 3″这样的element都选中, 或者你也可以写div.vcard和.vcard, 也能选到,但是,俄,严谨嘛,苏用的css编辑器是KDE自带的Kwrite,会把高级选择器显示为苏最喜欢的粉色,宽恕苏的完美主义吧……

5,嵌套评论有阴影,这个也很简单只需要用PS或者Gimp做一个阴影加上就好了(苏用Gimp),也是CSS 问题。切图稍微有一点讲究,就是只能横着切不能竖着切,因为你不知道人家留言会留多少高度。所以切一小块阴影,repeat-y做 [class~=depth-2]的背景,把最下面的底切下来作为ul.children的背景。

延伸:苏的评论是嵌套了两层,因为苏不是个无聊的人呢,不会像Google Wave上面有些人一样20多岁了玩套圈圈,一层一层又一层,但是从技术上这是要说的,因为可能有人就喜欢设置个10层。那样就不止是对 [class~=depth-2]做背景了,准确的写法应该是

li[id|=comment]:not[class~=depth-1]

,也就是说这个背景要给到id是comment-<?php comment_ID(); ?>的、除了第一层的所有li上。另外那个底部的处理也不能像苏现在这样直接截一条下来当底部咯,因为每一层的嵌套宽度都是不同的,我们至少需要2 个element来实现下面的底。首先是

li: last-child

, 这个好理解吧,每一层的最后一个li,可以把那个左下角截下来给它当背景。然后对第一层的最后一个li去掉这个背景,

li.depth-1: last-child {background: none;}

。其他的阴影可以交给ul.children。当然有像苏一样完美主义的人非要在这一条里面在实现一个右下角的圆角阴影效果也不是不可以滴,那就是

li: last-child p: last-child

这个element咯,把右下角效果交给它吧。

具体的css代码苏就不写咯,剩下的就是重复工作咯,毕竟苏已经把选择哪个元素加背景写出来了,剩下的无非就是padding, margin的调整让它们在一条线上罢了。

好,到现在CSS能做的工作苏已经做好了。下面轮到标题中就已经提到、但现在还没有出现的jQuery上场咯。

是不是非用到jQuery不行呢,很抱歉,在这个情况下,是的。苏是CSS党,如果是一个Accordin效果苏完全可以抛弃jQuery,ie对:hover伪类支持的不好,苏可以把代码写到一个<a>里面嘛 :-) 这里非jQuery不行是因为我们需要针对click做效果,css不行。

2,未读消息前面显示一个小绿条。这句的关键在于判断什么是未读。苏对服务器端不熟悉,所以苏这里无法说你这次 click一下表示读过,关闭网页重开,我就会记住,哦,你这条读过了阿。Google有那么大的服务器,有能力,而且它的每一个用户都是肯定有帐号的, 苏即使有那么大服务器也只能针对ip地址做一个mysql表,哦,这个ip读过这条评论,但你换个地方上网,或者极端情况你坐那里没动,路由器换跟线,苏 这里就又要重新记住你一回,总不能强制访客注册吧。所以按用户“记住”未读消息是不太可能的,我做WordPress不是做Google Reader。 苏从客户端对未读的解释就只能是你打开网页,所有的评论你都没读过。这一方面是苏的技术不够,或者说是花费的精力和所得到的效果完全不成比例,投入/产出 比不对,苏是经济学人呢~另一方面就是比如cnbeta,可能吧那种大站,一点开页面所有评论你都没读过的可能是存在的,而且是经常的,呵呵,苏已经开始 好高骛远了呢。

好咯,未读说完了,你可以直接写在你的模板里,comment-body后面加个class=”unread”。但是别忘记了,我们用的可是默认模板阿,是看不到这些的,没关系,用jQuery:

$(document).ready(function () { $(".comment-body").addClass("unread"); });

然后再对unread class做CSS,加上一个小绿条的背景。或者直接:

 $(document).ready( function () { $(".comment-body").css({' background', 'url(XXXXX.png) top left repeat-y '}); });

按照逻辑的配对(实际上苏也正是这么做的),接下来应该说的是7, 鼠标左键点击消息会出现一个绿色框选中该条消息,继续单击无法取消,只能点击别的消息或者离开该Wave,效果才会消失。单击过的消息前面的小绿条消失。

这个无论如何用css都做不了。代码比较简单,直接放代码吧:

$(".comment-body").click(function() {
$(this).removeClass("unread"); //去掉被点击的消息的小绿条;
$("[class~=comment-body]").removeClass("selected"); //如果其他的消息上面有绿框则去掉它们,用来保证只有一条消息是选中的;
$(this).addClass("selected"); //给选中的消息加绿框。
});

下面处理那个3作者评论头像右下角的小绿点。苏是用jQuery追加数据的方式实现的,代码是这样的:

$("li[class~=bypostauthor]").children(".comment-body").children(".vcard").children("img").after("<span class=\"postauthor\"></span>");

首先要选中作者评论,WP2.8自带的嵌套已经给出了两个比较特殊的class,一个就是byuser, 代表你在我的站上注册过,另外一个就是bypostauthor,文章作者。各位走过路过滴同学心里应该有所共鸣了吧,通过定义byuser的样式可以提 升访客体验。继续解释代码:选到文章作者评论的li,然后选到它的重孙img,就是Gravatar,然后在它的后面追加一个span。定义span的 css即可。为什么不追加div呢,因为会把后面的作者名字和发表时间挤到下一行去。BTW,不要用绝对定位的方式定义这个span的css, 因为绝对定位会从当前文档流中排除,很容易就覆盖了紧跟在后面的评论作者名字。可以用margin的负定位。

当然,对jQuery没有信心的同学完全可以用参考线量出这个圆点应该出现的准确位置,然后作为<cite class=”fn”>的背景,然后对cite进行绝对定位+z-index让它覆盖在Gravatar的上面 :-) 不过就是太麻烦咯。

下面是最后一个效果:6,鼠标放在消息下方会有一个蓝色圆框出来让你继续嵌套或者是续接这个嵌套层。

其实这个简单来说针对的主要是wordpress嵌套评论的reply按钮。用那个圆角方框完全替代reply按钮,再把它隐藏起来,鼠标滑过的时候显示,之后隐藏。很简单的一个jQuery效果吧。

但是它的难点在于,真正的Google Wave是可以让你选择是开始新的嵌套还是继续当前嵌套层的,也就是说可以把你的回复贴到别人嵌套层上面,开始一个新的同级ul。这个需要ajax的支援,苏会写在本系列文章的第二篇里面。

为了高度仿真Google Wave,我们也要让它能选择开始新的嵌套或者继续当前嵌套。好吧,苏的技术有限,现在还没想到好方法。但是“在一个已经有嵌套的评论下面显示‘继续当前 嵌套’,在没有嵌套的评论下面显示‘开始新的嵌套’“,这总归是可行的,不然我写那么多玩什么呢对吧……

用jQuery来说就是,先判断当前评论是不是第一层(因为苏只有两层,第二层就已经不能在继续“开始新的嵌套“咯),然后再判断第一层的元素下面 有没有嵌套(这个逐渐缩小的过程能理解吧,第二层是绝对没有嵌套的,判断第一层就行了),如果有嵌套就给一个继续当前嵌套的class,如果没有就给一个 开始新的嵌套的class。这是default主题的情况。代码:

$(".comment-body").mouseover(function() {
if ($(this).parent("li").hasClass("depth-1")) {           //判断是不是第一层
if($(this).parent("li").hasClass("parent")) {            //判断有没有嵌套
$(this).children(".reply").addClass("continue");
$(".continue").show();
} else {
$(this).children(".reply").addClass("insert");
$(".insert").show();
};
} else {
$(this).children(".reply").addClass("last");           //如果是第二层
} endif;
}).mouseout(function() {
$(".insert").hide();
$(this).children(".reply").removeClass("insert");
$(".continue").hide();
$(this).children(".reply").removeClass("continue");
});

不知道大家搞懂了没,苏的JS不强,所以用的效果都很简单的,大家可以在此基础上加效果。

延伸: 同样是多层的情况,专门写给那些无聊的同学的。

由于存在的层数未知, 这时候道理就应该反过来说咯,先知道最后一层,一层一层往上推,因为只有最后一层是特殊的,就是它不能再开始新的嵌套。判断最后一层的方法是: 判断有没有下家,这时不能用parent的方法来判断,因为他可能是中间某层,只需要判断这一层有没有ul.children就可以咯。另外还要判断 prevAll和nextAll有没有ul.children,避免出现正好判断在岔路上这种悲剧。

而至于背景,这时候也不适合用addClass的方式了,因为每一层宽度不同,要很多很多Class。苏之前也不懂怎么做,但是今天做 comments.js的时候发现了一个方法,就是:写一个递归变量,每次都+若干个px,然后把这个变量赋给width,这样只需要做一个最宽的没有最 左边图像的背景,再right top,然后对<div class=”reply”>做背景补全那个左上角,通过width就能画出宽度不同的reply按钮咯。

关于递归变量可以看这句:

$('#commentnum').text(parseInt(jQuery('#commentnum').html()) + 1);

好啦,总算写完这篇“技术文”咯,其实就是个想法,大部分代码我没贴是吧,但关键代码我都贴了对吧。这个做法是开发大家的想象力,因为自学的菜菜阶 段的想象力其实是最丰富的,为了实现一个结果会去想好多好多种方法,但是专业的设计师就不会,因为他们脑子里早就有最好的啦,你可以从他们网站上cp过 来,效果有了,但你什么也没学到不是么。吼吼,不教育人了,其实这一方面是苏对于那些代码也是一知半懂,写能写出来但要纠结好久,干脆就贴个想法咯;另一 方面是做ajax评论时候得到的教训,就去网上下了一个php一个js,搞定了。。。可是我依然不知道什么是ajax。

<!– 这篇文章为小女原创,小女完全明白其意思,可以转载,但是不可以歪曲事实,要么不转要么全转; 可以在此基础上继续开发,但请另起炉灶或保留原文的基础上加注释。此类无聊雷同文并不好找,如果真的有雷同,本人可能不愿起诉你,但心情不好对你发飙你也 请胳膊打折袖里藏~–>

原创文章,转载请注明: 转载自广陵散 `s 博客

本文链接地址: 用jQuery实现Google Wave样式的Wordpress评论(一)

Post Footer automatically generated by wp-posturl plugin for wordpress.