1、/* 人人网留言板所使用的扩展代码. 主要实现留言墙业务* requires ( base.js )* author auscar( huihua.linopi- )* version 1.0* date 2009-10-N*/* module XN.app* requires base.js/xn.app.gossip.js*/* 使用说明:* 由于留言板扩展代码是依附在留言核心代码之上的, 因此使用方法和留言板核心一样, 只是要再传几个参数, 下面是一个初始化的例子:* * /核心的初始化使用了默认配置* mentPost = new XN.app.Comment(* dashOwner
2、: 282079587,/当前的留言板是谁的* visiter : 282079587,/谁在看这个留言板* gossipCount : 570,/留言板拥有者有多少条留言,方便初次分页* isVip : false/是不是 vip* );* * 有一些必须的属性在 protype 的扩展当中已经注明.请看代码.* 核心留言板组件的初始化代码可以参见 xn.app.gossip.js*/* API:* */XN.namespace( app );/- 对 XN.app.Comment 对象进行扩展 -/ 主要是实现了留言的展示功能/-/ 扩展 xn.app.gossip.js 的 protot
3、ype$extend( XN.app.Comment.prototype ,/成员变量 -perPage : 20,/每一页所显示的留言数idRecentContact : recent_list,/最近联系人的容器(必须)idPagerWrapper : comment_pager,/分页的容器(必须)idLoadingWrap : comment_pager_wrapper,/loading 的容器(必须)idcontactSearch : contactSearchInput,/好友搜索的那个框(必须)idTitle : title_head,/“给 XXX“留言idNoticeWrap
4、per : notice,/一些消息显示的需要放在这里( 必须)reloadUrl : http:/gossip.+XN.env.domain,seeFriMode : false,/是否处于查看自己与好友之间的留言的模式isFirstChange : true,/切换最近联系人的时候, 将“悄悄话“设置为可用(disabled=false)以及checkBox 不勾选.但是第一次的时候不用这么做/-msg : empty : 留言不能为空,sureDelContact : 确定要删除此联系人吗?,failDelContact : 出了点问题, 稍候再试试看.,failNetError : 您
5、的网络出了点问题, 稍候再试试看.,url : commentPost : http:/gossip.+ XN.env.domain +/gossip.do,add : http:/gossip.+ XN.env.domain +/gossip.do,del : http:/gossip.+ XN.env.domain +/delgossip.do,delContact : /delcontact.do,catche : ,/* 核心留言板控件初始化完毕之后, 就会执行这里的额外初始化*/xinit : function() this.initContactList();this.initCo
6、ntactSearch();this.xbindEvent();,/* 扩展的留言代码的事件绑定*/xbindEvent : function()this.addEvent( noComments ,this.showNone);var that = this;this.addEvent( changePerson , function( o )that.resetServerParams();/重置与服务器之间约定的参数$( that.idTitle ).innerHTML = 给 + ( o.name | ) + 留言;this.curName = o.name;/这个属性是为了方便在 c
7、heckForm 中动态构造一个正则表达式,以检测用户的输入, 然后作出相应的判断, 见 xn.app.Comment 的 checkForm 函数/$( that.idOfTextarea ).value = 回复+ o.name +:;$( that.idTextArea ).value = 回复+ o.name +:;/$( that.idLeaveWord ).value = o.id;that.hideNotice();$( that.idLeaveWord ).value = o.id;/TODO: 查看是否还是有没有阅读的留言, 如果没有, 则触发事件 noToRead 事件.触
8、发这个事件是为了让某些 tooltip 出现if( !that.hasRecent() )that.fireEvent( noToRead );if( that.textareaHelper )that.textareaHelper.focus();/切换最近联系人的时候, 将 “悄悄话“设置为可用(disabled=false)以及 checkBox 不勾选.但是第一次的时候不用这么做if(that.isFirstChange)that.isFirstChange = false;else_whisper = $( that.idWhisper );if(_whisper)_whisper.
9、checked = false;/_whisper.disabled = false;);this.addEvent( noCommentsErr , function()that.showNotice(msg : 没有更多的留言啦!); );this.addEvent( beforeUpdatePager , function()that.resetServerParams(););,/* 通过检查 ul 的 li 是否还有已读 class 来判断当前的留言板已经没有了未读留言*/checkToRead : function()if( !this.hasRecent() )this.fire
10、Event( noToRead );,/* 遍历指定的 ul, 并将 ul 内的 li 转化成一个最近联系人的 tab*/initContactList : function()if( !$( this.idRecentContact ) )return;var that = this;this.rc = new XN.ui.tabView(/rc is short for “recent contact“activeClass : select);var tab_lis = $( this.idRecentContact ).getElementsByTagName(li);/逐个将 li
11、转化为 tabXN.array.each( tab_lis , function( i , li )that.rc.addTab(label : li.id,/li 的 id/当该 tab 被激活时,我们希望发送一个 ajax 请求, 获得与某个用户有关的留言 , 同时更新pager,因为每一个用户的留言数都不一样onActive : function()var idRegx = /_(d+)$/;/TODO:这个可以移出来var m = idRegx.exec( li.id );/从缓存中取这个用户的留言,如果有就用, 没有就从服务器取/ if( that.catche m1 )/ that
12、.saveServerParams( that.catche m1 );/ that.updatePager( m1 , that.catche m1 .gossipCount );/同时更新 pager,因为每一个用户的留言数都不一样/ alert(6);/ that.curpage = 0;/ return;/ that.fireEvent(beforeUpdatePager);that.fetchComment(userId : m1,resource : li.getAttribute( r ),callBack : function( o )/ o 是服务器返回的对象that.sav
13、eServerParams( o );that.updatePager( m1 , o.gossipCount );/同时更新 pager,因为每一个用户的留言数都不一样that.curpage = 0;);/当 tab active 的时候, 就去掉那浅色的背景li.delClass( unread );that.fireEvent( changePerson , name : li.getElementsByTagName(a)0.innerHTML,id : m1);););/end each/- 绑定事件 -this.rc.addEvent( noTabs, function()loc
14、ation.href = that.reloadUrl;);,_getContactList : function()return this.rc; /rc is short for “recent contact“,/* 删除一个最近联系人* param string userId - 最近联系人的 id*/delContact : function( userId )var id = user_ + userId;var t = $(id);if( treturn;var that = this;/ XN.DO.confirm(/ message : that.msg.sureDelCon
15、tact,/ callBack : function( yes )/ if( yes )/ 发送删除的请求new XN.net.xmlhttp(url : that.url.delContact,method : post,data : XN.array.toQueryString(guest : userId),onSuccess : function( r )var o = eval( (+r.responseText + ) );if( o.code )/如果不是 0, 说明删除联系人失败了XN.DO.alert( that.msg.failDelContact );elsethat.r
16、c.delTab(id);if(that.startUserTab = id)location.href = that.reloadUrl;,onError : function()XN.DO.showError( that.msg.failNetError ); ); / / / );,/* 初始化分页器*/initPager : function()/设置分页器var pager1 = this.pager = new XN.ui.pager(showCount : 5);/pager1.setPageCount( Math.ceil( this.gossipCount / this.pe
17、rPage );this.syncPager();/同步主从分页器(如果有的话)var pr = $( this.idPagerWrapper );pr.className = pagerpro;pr.setContent( pager1 );var that = this;pager1.addEvent( pageChange , function( num )/第一次的 pageChange 不响应, 因为第一次服务器端已经在页面上方了数据, 不需要调用fetcheComment 来向服务器获取留言if (!that.notfirstTime) that.notfirstTime = tr
18、ue;elsethat.fetchOwerComment( num - 1 );that.fireEvent( changeOver ););pager1.setPageCount( Math.ceil( this.gossipCount / this.perPage );pager1.setCurrentPage( 0 );/第一次的时候显示第一页, 但是第一并不真正执行 pageChange事件监听器里面的代码,/* 更新 pager 然后绑定新的 pageChange 事件监听器.再然后就请求第一页的留言内容.* * 当点击一个 tab 更改了最近联系人以及搜索一个好友的留言的时候, 分
19、页器应该显示当前用户与该好友之间的留言的分页数. 所以要更新一下分页器* param string userId - 获取当前查看留言板的用户(visiter)和 userId 所制定的用户之间的留言内容* param number gossipCount - userId 指定的用户的留言数目.那我到底是怎么得到的呢?其实 updatePager 主要是在 fetchComment 内被调用, fetchComment 会给 updatePager 传这个参数* param Object isOwner - 这个值决定第一页的请求发送到哪里,是请求用户自己的留言板的内容?还是请求用户与某个好
20、友之间留言墙的内容?*/updatePager : function( userId , gossipCount , isOwner )/that.fireEvent(beforeUpdatePager);XN.debug.log( update pager.+ userId );this.seeFriMode = true;/设置这个值为 true, 表示留言板处于查看自己与某个用户之间的留言的模式var that = this;/更新一下 pager /重新建立一个 pagerthis.pager = new XN.ui.pager(showCount : 5);this.pager.in
21、itCall = true;/即将进行首次 pageChange 请求 , 做个记号, 第一次不真正运行pageChange 内的代码/alert( Math.ceil( gossipCount / that.perPage ) );var t = $( this.idPagerWrapper );t.className = pagerpro;t.setContent( this.pager );/绑定新的分页器 pageChange 事件监听器.this.pager.addEvent( pageChange , function( num )if (that.isLoading) /that
22、.tooQuick();return;XN.debug.log( click : + that.hostBeginId + + + that.hostEndId + + that.guestBeginId + + that.guestEndId );if ( that.pager.initCall ) /第一次不请求服务器that.pager.initCall = false;return;/fetch commentvar p = userId : userId,pageNum : num - 1,hostBeginId : that.hostBeginId,hostEndId : that
23、.hostEndId,guestBeginId : that.guestBeginId,guestEndId : that.guestEndId,destpage : num - 1,curpage : that.curpage/这个变量时是要告诉服务器, 用户请求到了分页的端点值了 . 这么做只是为了配合后台的分页技术方案 if( num = that.pager.pageCount() )p.boundary = end;else if( num = 1 )p.boundary = begin;XN.debug.log( current page in obj : + that.curpa
24、ge );isOwner? that.fetchOwerComment( p ) : that.fetchComment( p , function( o )/将一些服务器返回的参数保存, 待后面返回给服务器XN.debug.log( params from server : + o.hostBeginId + + o.hostEndId + + o.guestBeginId + + o.guestEndId);that.saveServerParams( o );that.curpage = num - 1;/更新一下XN.debug.log( curpage : + that.curpag
25、e );XN.debug.log( commentPost : + commentPost.hostBeginId + + + commentPost.hostEndId + + commentPost.guestBeginId + + commentPost.guestEndId ););that.addEvent( changeOver ););/ end add event/this.syncPager();/主从分页器同步that.pager.setPageCount( Math.ceil( gossipCount / that.perPage ) );/总共的页数that.pager
26、.setCurrentPage( 0 );/设置当前页面为第一页, 但是不会真正运行 pageChange 事件的监听器/如果只有一页, 就不需要翻页了if( Math.ceil( gossipCount / that.perPage ) 您的请求过于频繁, 请稍候再试.);,/* */initContactSearch : function()if( !$( this.idcontactSearch ) )return;var that = this;var fInput = $( this.idcontactSearch );new XN.FORM.inputHelper(fInput).
27、setDefaultValue( 添加联系人 . );var selector = new XN.ui.friendSelector(id:fInput);selector.menu.setWidth(139);selector.onSelectOne = function(r)fInput.value = ;/添加一个联系人到最近联系人列表中var newConcat = $element(li);newConcat.id = user_ + r.id;if ($(newConcat.id) that.rc.setCurrentTab( newConcat.id );/newConcat拼写
28、错误, 懒得改了return;/如果已经有了这个联系人,就不让加进去了,而是高亮显示那个用户/TODO:;newConcat.innerHTML = + r.name + ;/newConcat.innerHTML = + r.name + ;/alert(r.id + r.name);$( that.idRecentContact ).insertBefore( newConcat, $( that.idRecentContact ).firstChild );/ alert(5);/往联系人列表中添加新联系人, 闭包不是必须的, 一时手误 , 懒得改了.(function( id )tha
29、t.rc.reset();/清除掉高亮that.rc.addTab(label : user_+id,onActive : function()/XNment.fetchComment( id );that.fireEvent(beforeUpdatePager);that.fetchComment( userId : id,callBack : function( obj )that.saveServerParams( obj );that.updatePager( id , obj.gossipCount ); );that.fireEvent( changePerson , name :
30、 r.name,id : id );,active : true,true);/添加 tab 完毕之后, 马上获取用户的第一页 comment/that.updatePager( id , obj.gossipCount );that.fetchComment(search : 1,userId : id,callBack : function( obj )/保存服务器返回的参数that.saveServerParams( obj );/更新一下 pagerthat.updatePager( id , obj.gossipCount ); );that.fireEvent( changePer
31、son , name : r.name,id : id );/XNment.updatePager();/同时更新一下 pager 的行为)(r.id);,make : function( str )var t = $element( div );t.innerHTML = str;/alert( make : + t.firstChild.nodeType = 1 );return t.firstChild.nodeType = 1? $(t.firstChild) : $(t.firstChild.nextSibling);,makeNoneDiv : function()/this.no
32、neDiv = this.make( 你们之间还未有过留言对话噢。有情有义的你,想到有这个好友,就说点什么吧。 );this.noneDiv = $element( div );this.noneDiv.innerHTML = 你们之间还未有过留言对话噢。有情有义的你,想到有这个好友,就说点什么吧。;,showNone : function()/this.textareaHelper.focus();var t = $( this.idCmtContainer );if( !t )return;if( !this.noneDiv )this.makeNoneDiv(); t.innerHTML
33、 = 你们之间还未有过留言对话噢。有情有义的你,想到有这个好友,就说点什么吧。;this.pager.setPageCount(0);/ t.innerHTML = 噢喲没有这个用户的留言哦!给 TA 写点什么吧!;this.textareaHelper.focus();this.noneDiv.show();this.hideNotice();,buildLoading : function()if( this.loading )return;this.loading = $element(div);this.loading.innerHTML = 正在载入.;/this.loading.s
34、tyle.position = absolute;$( this.idLoadingWrap ).appendChild( this.loading );,showLoading : function()if( !this.loading )this.buildLoading();this.loading.show();window.location = #navBar;/定位到页面的上端this.isLoading = true;,hideLoading : function()/XN.element.hide( this.loading , fade );this.loading.hide
35、();this.isLoading = false;,addSlavePager : function( pgr )if ( !this.slaves ) this.slaves = ;this.slaves.push( pgr );,syncPager : function()var that = this;if( !this.slaves | !this.slaves.length )return;/没有从 pager 就不用同步了XN.array.each( this.slaves , function( i , pgr )XN.ui.pager.sync( that.pager, pg
36、r );/XN.ui.pager.sync( pgr , that.pager );pgr.setPageCount( that.pager.pageCount() ););,/* 方法提供给后台工程师调用, 用以选中其中一个联系人* param Object userId*/recentSelect : function( userId )if( ! this.rc )return;/如果有缓存池 以及 传入了一个最近联系人的所有留言 , 就把这个联系人的留言缓存起来if( this.catche this.rc.setCurrentTab( user_ + userId );this.st
37、artUserTab = user_ + userId;,showNotice : function( o )/如果有这个 cookie, 说明已经不是第一次了 , 不用显示提示了if ( XN.cookie.get(o.noticeId) ) return;if( !this.noticeSpan )this.noticeSpan = $element( p );/下面就是很简单的 DOM 元素的拼装var n = this.noticeSpan;var ns = n.style;ns.textAlign = center;ns.background = #fff9d7;ns.border
38、= solid 1px #d7b013;ns.padding = 5px 15px 5px 5px;ns.margin = 8px 0 0;ns.display = block;ns.position = relative;ns.textAlign = left;if( typeof o = string )this.noticeSpan.innerHTML = o;return;if( o.id )var name = + this.getCurName() + ;this.noticeSpan.innerHTML = o.msg | 功能升级: 这里是你和+ name +的留言板,你可以在
39、此给+ name +留言,也可以怀怀旧,看看你们之间都说过些什么。;/如果这条 Notice 需要被关闭 , 就给它生成一个关闭按钮if( o.canDel )var a = $element( a );a.className = x-to-hide;a.href = “#nogo“;var as = a.style;as.position = absolute;as.top = 3px;as.right = 3px;this.noticeSpan.appendChild( a );var target = o.target | this.idNoticeWrapper;if( !$( tar
40、get ) )return;$( target ).setContent( this.noticeSpan );/点击关闭按钮, 设置一个 cookie, 说明来过了, 这样下次就不显示这个提示了a.onclick = function( e )e = e | window.event;XN.event.stop( e );/alert( o.noticeId );XN.cookie.set( o.noticeId , 1 , 360);$( target ).hide();/最后把 Notice 显示出来this.noticeSpan.show();,hideNotice : functio
41、n()if( this.noticeSpan )this.noticeSpan.hide();,hasRecent : function()if( !this.recents )this.recents = $( this.idRecentContact );if( !this.recents )return;var tabs = this.recents.getElementsByTagName( li );if( !tabs.length )return;var regx = /recent/;/TODO:似乎要改成 unread 吧.var has = false;XN.array.ea
42、ch( tabs , function( i , tab )if( regx.test(tab.className) )has = true;return has;);return has;,getCurName : function()if( !this.recents )this.recents = $( this.idRecentContact );if( !this.recents )return;var tabs = this.recents.getElementsByTagName( li );if( !tabs.length )return TA;var cur = this.r
43、c if( !cur )return;cur = $( cur.key );tryreturn cur.firstChild.nodeType = 1 ? cur.firstChild.innerHTML : cur.firstChild.nextSibling.innerHTML;catch(e)return TA;);/- tooltip 工具条提示类 -/ 用来显示一个 tooltip, 主要是封装了 XN.ui.menu /-XN.namespace( ui.tooltip );XN.ui.tooltip = function( params )if( params )$extend(
44、 this , params );this.init();XN.ui.tooltip.ids = 0;XN.ui.tooltip.prototype = init : function()var that = this;var div = $element(div);div.id = tooltip_ + XN.ui.tooltip.ids+;var ds = div.style;ds.background = #fff9d7;ds.border = solid 1px #d7b013;ds.padding = 3px 15px 3px 3px;div.innerHTML = this.msg
45、 | 留言板可以添加图片了,现在就试试,送个惊喜吧! 关闭;var a = $element( a );var as = a.style;a.className = x-to-hide;as.position = absolute;as.top = 0;as.right = 0;if( this.cookie )var c = this.cookie;XN.event.addEvent( a , click ,function(e)e = e | window.event;XN.event.stop( e );XN.cookie.set( c.key , c.value , c.expire | 10000 );that.tip.hide();); var div_arrow = $element( div );var das = div_arrow.style;das.back