好多人都在博客上弄了个读者墙,我之前也搞过,但是换了新主题之后就没再添加了。所以抽了个时间,在links页面加了读者墙,展示的是最近三个月内的评论数量在前72名的访客头像。围观我的读者墙请移步此处。
读者墙部分加了个JS效果,鼠标移上去会在旁边打开一个侧滑面板,显示访客的姓名和评论数量等信息。我将这个效果封装了一下,与大家分享。
(注:因为涉及到代码的bug修复、代码更新等因素,demo中的代码不会同步更新,所以JS代码以本文中所贴为准。bug修复一: 修正浏览器宽度获取少计算滚动条宽度的问题。)
/*!
* author: liuqiqi
* date: 2010/09/01
*/
var Class = {
create: function() {
return function() {
this.init.apply(this, arguments);
}
}
}
var PicWall=Class.create();
PicWall.prototype={
init:function(wrapId,infoId,picClass,textClass){
this.wrap=this.$(wrapId);
this.info=this.$(infoId);
this.picClass=picClass;
this.textClass=textClass;
this.timer="";
this.pics=this.$$(this.picClass, 'li', this.wrap)
for (var i = 0; i < this.pics.length; i++) {//给每张图片加上事件监听
this.addListener(this.pics[i], 'mouseover', this.bind(this.show,this), false);//用bind给事件函数绑定正确的对象
}
},
show:function(e){
//这里要注意,页面结构li标签下必须是头像图片img,并且不要在img外再加a标签,否则下面这句代码获取不到正确的事件源节点
var node=e.target?e.target.parentNode:e.srcElement.parentNode;
this.info.style.display = "block";
this.info.innerHTML = node.innerHTML;//将图片加到div#info中
var point = this.getMousePoint(e);//获取事件发生时鼠标坐标
var picXY = this.getPicXY(node);//获取当前图片的坐标
var windowx = document.documentElement.clientWidth || document.body.clientWidth;//浏览器可视区域宽高(前者为网页头声明W3C标准后正常获取可视区域宽度,后者为未声明标准情况下IE获取宽度)
var maxleft = this.getPicXY(this.wrap).x + this.wrap.clientWidth;//alert(maxleft);return; 放置图片列表容器的右边框x坐标
if (picXY.x + 156 >; maxleft) {//信息框展开后大于容器右边框,则使信息框向左滑动展开
this.info.style.left = "auto";
this.info.style.right = windowx - picXY.x - 53 + "px";
this.addClassName(this.info, 'right');//此处是将头像浮动到右边显示
}
else {//正常情况下信息框在右边滑动展开
this.removeClassName(this.info, 'right');
this.info.style.right = "auto";
this.info.style.left = picXY.x - 3 + "px";
}
this.info.style.top = picXY.y - 3 + "px";
this.addListener(this.info, 'mouseout', this.bind(this.unshow,this), false);
clearInterval(this.timer);
var starttime=new Date(), nowtime;
this.timer = setInterval(this.bind(function(){//宽度变换
nowtime=new Date();
if (nowtime - starttime < 300) {
this.info.style.width = 53 + Math.floor((nowtime - starttime)/300*100)/100*103 + "px";
}
else {
clearInterval(this.timer);
this.$$(this.textClass,'span',this.info)[0].style.display="block";
}
},this), 5)
},
unshow:function(e){
var node=e.target?e.target.parentNode:e.srcElement.parentNode;
var point = this.getMousePoint(e);
var picXY = this.getPicXY(node);
//通过坐标比对,判断鼠标是否移出信息框区域
//下面这个if括号语句可以删除,那样鼠标将不能放到文字区域
if (point.x <; picXY.x || point.x > picXY.x + node.clientWidth || point.y < picXY.y || point.y > picXY.y + node.clientHeight) {
clearInterval(this.timer);//清除定时器
this.info.style.display = "none";
this.info.style.width = "56px";//宽度重置初始化
}
},
$:function(id){//由id获取结点对象
return document.getElementById(id);
},
$$:function(c, t, p){//c:className, t:tagName, p: praentNode。根据节点的class、结点标签类型、及其父级结点来获取一组符合条件的结点数组
var at = p.getElementsByTagName(t);
var ms = new Array();
var r = new RegExp('(^|\\s)' + c.replace(/\-/g, '\\-') + '(\\s|$)');
var e;
for (var i = 0; i < at.length; i++) {
e = at[i];
if (r.test(e.className)) {
ms.push(e)
}
}
return ms
},
getMousePoint:function(ev){
var x,y;
if (typeof window.pageYoffset!= 'undefined') {
x = window.pageXOffset;
y = window.pageYOffset
}
else
if (typeof document.compatMode != 'undefined' &;& document.compatMode != 'BackCompat') {
x = document.documentElement.scrollLeft;
y = document.documentElement.scrollTop
}
else
if (typeof document.body != 'undefined') {
x = document.body.scrollLeft;
y = document.body.scrollTop
}
x += ev.clientX;
y += ev.clientY;
return {'x','y':y};
},
getPicXY:function(o){
var x=y=0;
do {
x += o.offsetLeft || 0;
y += o.offsetTop || 0;
o = o.offsetParent;
} while (o);
return {'x','y':y};
},
bind:function(f,o){
return function(){
return f.apply(o,arguments);
}
},
hasClassName:function(o, c){//判断o是否具有值为c的className
return new RegExp("(?:^|\\s+)" + c + "(?:\\s+|$)").test(o.className);
},
addClassName:function(o, c){//给o添加名为c的className
if (!this.hasClassName(o, c)) {
o.className = [o.className, c].join(" ");
}
},
removeClassName:function(o, c){//删除o的值为c的className
if (this.hasClassName(o, c)) {
var a = o.className;
o.className = a.replace(new RegExp("(?:^|\\s+)" + c + "(?:\\s+|$)", "g"), " ");
}
},
addListener:function(e, n, o, u){//监听设置封装函数
if(e.addEventListener) {
e.addEventListener(n, o, u);
return true;
} else if(e.attachEvent) {
e['e' + n + o] = o;
e[n + o] = function() {
e['e' + n + o](window.event);
};
e.attachEvent('on' + n, e[n + o]);
return true;
}
return false;
}
}
使用这段JS代码,你需要注意下你的页面结构,要在一个固定ID1的div中输出若干li标签,li标签也要有一个className2,然后在li标签中输出头像图片,同样的关于访客的姓名、评论数量也要在li标签下,并且放到一个span标签中,这个span标签页给加个className3,最后在页面中加个显示访客信息的div,ID4固定。
关于页面结构你可以使用firebug或相关工具查看我的友情链接页面的的读者墙的页面结构。也可以下载此demo包。(2010.10.28,原包中代码已经老旧,此处乃最新代码)
页面结构写好了,就可以使用new PicWall()来使用上面的js了,它的四个参数分别是上面的1、2、3、4标注。即最外层的div id,显示信息的div id,li标签的className,li标签下放置的读者信息的span标签的className。比如,我的友链页面的读者墙即使用
1: new PicWall('commentsWall','info','pic','text');
来调用JS。commenswall是我的读者墙那个大div的id,info是一个空的div的id,pic是li标签的class,text是头像旁的span标签的class。更详细的下载demo包自行查看。CSS样式代码也在demo包里。
