\
\
\
' + v.title + '\
' + v.time + '\
\
';
var remain = v.containIds.length - self.conf.subCount;
details[i]='\
\
\
- \
\
' + self.ubbDecode(v.longTitle) + '\
\
\
\
\
暂没有新通知
\
查看其它 0 条\
';
});
$('.notice_list_con .notice_content', wrap)[insert](list.join(''));
$('.detail_con .notice_content', wrap)[insert](details.join(''));
self.changeToNickname();
},
fillDetail: function (detail, data) {
if(!data || !data.data || !data.data.length) return;
var bodyTpl = data.bodyTpl
, self = this
, dl = $('dl', detail)
, html
;
data = data.data;
if (data[0].body) {
html = $.map(data, function (v) {
return self.feTemplate(bodyTpl).render({
userlink:self.conf.space + v.from_user,
from_user:v.from_user,
body:self.ubbDecode(v.body),
time:v.time
});
}).join('');
if (html) {
dl.append(html);
var remain = dl.attr('data-ids').split(',').length - data.length
, url = data[0].url
;
if(remain > 0 && url) {
$('.notifications_more', detail).html(function (i, v) {
return v.replace(/\d+/g, remain);
}).attr('href', url).addClass('block');
}
}
}
if (!html) {
$('dt .count_down', detail).html(data[0].time);
detail.data('loaded', true);
}
self.changeToNickname(dl);
},
/**
* 显示列表的回调包装。和getUnreads,getAllReaded配合使用,包含一些通用的操作,以及触发必要的事件
* @param {Function} callback 当正常获取到数据时的回调
* @return {Function} 包装之后的回调函数
*/
showListCbWrap: function (callback) {
var self = this;
return function (err, data, loading) {
if (err) {
self.emit('list_showed', [err]);
} else {
callback && callback(err, data, loading);
if (!loading) {
var list = $('.notice_list_con .notice_content > .list', self.Dom.wrap);
// 调整可见消息数量
if (list.filter(':visible').length === 0) {
var n = list.filter('.unread').length;
if(n < self.conf.count) {
n = self.conf.count;
}
list.slice(n).remove();
$('.detail_con .notice_content > *', self.Dom.wrap).slice(n).remove();
}
list.show();
self.slideReset();
self.emit('list_showed');
}
}
};
},
error: function (msg) {
var self = this, func = arguments.callee;
if(func.init === undefined) {
func.ele = $('.error', self.Dom.wrap);
self.on('panel_showed detail_showed', function () {
func.ele.hide();
});
func.init = true;
}
msg = friendlyErrors[msg] !== undefined ? friendlyErrors[msg] : msg;
func.ele.toggle(!!msg).html(msg);
},
invokeAPI: function (url, params, opts, callback) {
var self = this
, opts = opts || {}
, callback = callback || self.emptyCb
;
self.lock(opts.lock === undefined || opts.lock ? url : null, function (err, unlock) {
if(err) {
callback(err);
return;
}
var done = opts.loading === undefined || opts.loading ? self.loading(opts.container) : self.wrapCb(false)
, data
, completed = false
, complete = function (xhr, status) {
if(completed) return;
done(function (loading) {
if(status && status !== 'success') {
callback(status, null, loading);
} else {
if(data.status !== 200) {
callback(data.error || data.status, data, loading);
} else {
if(opts.list) {
// /detail/i.test(url) && (data.data = []); // DEV
self.toggleEmpty(!loading && data.data && !data.data.length, opts.container, opts.list);
}
callback(null, data, loading);
}
}
unlock();
completed = true;
});
}
;
setTimeout(function () {
complete(null, 'timeout');
}, 20000);
$.ajax({
url: self.conf.api + url,
data: params,
dataType: 'jsonp', // TODO jsonp方式调用不能产生正确的timeout错误等,考虑换成支持跨域的xhr(在ff chrome ie8+)
success: function (json) {
if(completed) return;
data = json;
},
complete: complete
});
});
},
getUnreads: function (callback) {
var self = this;
self.invokeAPI('/get_unread?jsonpcallback=?', {}, {
container: '.notice_list_con',
list: '.notice_content > .list'
}, function (err, data, loading) {
self.fillList('prepend', data);
callback && callback(err, data, loading);
});
},
doaction : function(data,callback){
var self = this;
self.invokeAPI('/do_action?jsonpcallback=?', {
id:data.id,
dataApi:data.dataApi+"?me="+currUser.username+'&'+data.args,
}, {
}, function (err, data, loading) {
callback && callback(err, data, loading);
});
},
getAllReaded: function (callback) {
var self = this;
self.invokeAPI('/get_all?jsonpcallback=?', {
username: currUser.username,
status: 1,
count: self.conf.count || 5,
subcount: self.conf.subcount || 5
}, {
container: '.notice_list_con',
list: '.notice_content > .list'
}, function (err, data, loading) {
self.fillList('append', data);
callback && callback(err, data, loading);
});
},
setAllReaded: function(){
if(!localUreadData.length){
return;
}
this.setReaded([],function(){
$(".csdn_note .unread").each(function(i){
$(this).removeClass("unread");
localUreadData=[];
});
});
},
setReaded: function (data, next) {
var self = this;
self.invokeAPI('/set_readed?jsonpcallback=?', {
ids: $.map(data, function (i) {
return i.containIds.join();
}).join()
}, {
loading: false
},function(data){
next&&next(data);
});
},
getlocalUnread: function(){
return localUreadData;
},
isGetAll: function(){
return hasGetData;
},
isHasNewMsg: function(){
return hasNewMsg;
},
getDetail: function(detail, start, limit){
var self = this
, ids = $('dl', detail).attr('data-ids').split(',')
;
start = start || 0;
limit = limit || self.conf.subCount;
if (ids.length > 0) {
self.invokeAPI('/get_details?jsonpcallback=?', {
ids: ids.slice(start, start + limit).join()
}, {
container: detail,
list: 'dl > dd',
lock: false
}, function (err, data) {
if (err) {
self.error(err);
} else {
self.fillDetail(detail, data);
}
});
}
},
/**
* 动画切换
* @param {jQuery Object} from 动画开始的元素
* @param {jQuery Object} to 动画结束的元素
* @param {String} direction to在from的左边还是右边, left right
*/
goSlide: function(from, to, direction) {
var self = this
, speed = 110
// + 3000 // DEV
, offsetW = from.width()
, content = to.parents('.notice_content:first')
, fromComplete, toComplete
;
self.emit('goSliding');
if (!to.hasClass('curr')) {
from.removeClass('curr');
to.addClass('curr');
}
from.css({
position: 'relative'
});
to.css({
position: 'absolute'
, top: 0
, left: (direction === 'left' ? -offsetW : offsetW) + 'px'
, width: offsetW
}).show();
content.height(function (i, v) {
return v - from.height() + Math.max(from.height(), to.height());
});
fromComplete = function () {
from.css('position', '').hide();
};
from.animate({
left: (direction === 'left' ? offsetW : -offsetW) + 'px'
}, speed, fromComplete);
toComplete = function () {
to.css({
position: ''
, top: ''
, left: ''
});
content.css('height', '');
};
to.animate({ left: 0 }, speed, toComplete);
self.Dom.wrap.one('goSliding', function () {
from.stop();
fromComplete.call(from[0]);
to.stop();
toComplete.call(to[0]);
});
return this;
},
slideReset: function() {
var self = this
, container = $('.notice_list_con .notice_content', self.Dom.wrap)
, items = container.children().filter(':visible')
;
$('.notifications', this.Dom.wrap).eq(0).addClass('curr').show().end()
.slice(1).hide();
;
if(items.length > self.conf.count) {
// container.css({
// overflow: 'auto'
// , height: '255px'
// });
container.addClass("hover-overflow");
}
},
/*
* 【LOGIC】检查登录
*/
checkLogin: function(callback) {
try{
currUser.username = getCookie("UserName") || currUser.username;
currUser.userInfo = getCookie("UserInfo") || currUser.userInfo;
currUser.username && callback && callback(currUser.username);
}catch(e){
log(e);
}
},
initRealtime: function () {
var self = this;
// 兼容独立和合并的realtime.js
if(csdn.RealtimeClient === undefined) {
$.ajax({
url: self.staticUrl(self.conf['realtime.js'])
, dataType: 'script'
, cache: true // 已通过staticUrl对外链文件提供了缓存支持,getScript()可能会始终在url结尾加时间戳
, success: arguments.callee.bind(self)
});
return;
}
self.conf['socket.io.js'] = self.staticUrl(self.conf['socket.io.js']);
self.realtimeClient = new csdn.RealtimeClient($.extend({
channel: currUser.username
}, self.conf), function (msg) {
// 分发收到的实时消息
if(typeof msg === 'object') {
if(msg.setReaded) {
self.emit('receive_setreaded', [msg.setReaded]);
}
if(msg.initUnreadIds&&msg.initUnreadIds.length){
hasNewMsg = true;
self.emit('receive_unreads', msg);
}
if(msg.realtimeMsg){
hasNewMsg = true;
localUreadData = localUreadData.concat(msg.data);
self.emit('receive_unreads', msg);
}
}
});
},
/*
* UBB转义
*/
ubbDecode : function(content){
var _this = this;
content = $.trim(content);
var re = /\[code=([\w#\.]+)\]([\s\S]*?)\[\/code\]/ig;
function replaceQuote(str) {
var m = /\[quote=([^\]]+)]([\s\S]*)\[\/quote\]/gi.exec(str);
if (m) {
return str.replace(m[0], '');
} else {
return str;
}
}
var codelist = [];
while ((mc = re.exec(content)) != null) {
codelist.push(mc[0]);
content = content.replace(mc[0], "--code--");
}
content = replaceQuote(content);
content = content.replace(/\[reply]([\s\S]*?)\[\/reply\][\r\n]{0,2}/gi, "回复$1:");
content = content.replace(/\[url=([^\]]+)]([\s\S]*?)\[\/url\]/gi, '$2');
content = content.replace(/\[img(=([^\]]+))?]([\s\S]*?)\[\/img\]/gi, '');
content = content.replace(/\r?\n/ig, "
");
if (codelist.length > 0) {
var re1 = /--code--/ig;
var i = 0;
while ((mc = re1.exec(content)) != null) {
content = content.replace(mc[0], codelist[i]);
i++;
}
}
content = content.replace(/\[code=([\w#\.]+)\]([\s\S]*?)\[\/code\]/ig, function (m0, m1, m2) {
if ($.trim(m2) == "") return '';
return '' + _this.HTMLEncode(m2) + '
';
});
content = content.replace(/(
|
)/ig, function (m0) {
if ($.trim(m0) == "") return '';
//return _this.HTMLEncode(m0);
return " ";
});
//针对转义的"做处理
content = content.replace(/(\\"e\;|\"e\;)/ig, function (m0) {
if ($.trim(m0) == "") return '';
//return _this.HTMLEncode(m0);
return "";
});
return content;
},
HTMLEncode : function(str) {
var s = "";
if(str.length == 0) return "";
s = str.replace(/&/g, "&").replace(//g, ">").replace(/\'/g, "'").replace(/\"/g, """);
return s;
},
/**
* 简单模板替换
* @param {String} tempStr 待替换字符串
* @return {String} 替换后的html
*/
feTemplate : function(tempStr){
// TODO 未处理模板字段重复出现的问题 [fixed]
// 未处理返回的模板对象复用的问题 [fixed]
// 测试用例 //jsfiddle.net/SdzfU/2/
return {
render:function(conf){
var result=tempStr;
for(var name in conf){
if(conf.hasOwnProperty(name)){
result=result.replace(new RegExp("{"+"%"+name+"%"+"}","g"),conf[name]);
}
}
return result;
}
}
}
};
})(window);
(function($, window, undefined) {
if ($ === undefined) {
// 按需加载jQuery
var done = false
, callback = arguments.callee
, script = document.createElement('script')
, head = document.getElementsByTagName('head')[0] || document.documentElement
;
script.src = '//csdnimg.cn/www/js/jquery-1.4.2.min.js';
script.charset = 'utf-8';
script.onload = script.onreadystatechange = function () {
if(!done && (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete')) {
done = true;
try {
callback(window.jQuery, window);
} catch(e) {
window.console && window.console.log(e);
}
script.onload = script.onreadystatechange = null;
if(head && script.parentNode) {
head.removeChild(script);
}
}
};
head.insertBefore(script, head.firstChild);
return;
}
// 初始化通知面板
var script = $("#noticeScript")
, opts = {
instance: 'csdn_note'
, btnId: script.attr('btnId') || 'header_notice_num'
, wrapId: 'note1'
}
;
opts.btn = $('#' + opts.btnId);
if(!opts.btn[0]) {
return;
}
$.map(['instance', 'wrapId'
, 'realtime', 'api', 'app', 'space', 'count', 'subCount'
, 'staticUrl', 'cssUrl'
, 'realtime.js', 'channel', 'socket.io.js', 'socket.io options'], function (v) {
opts[v] = script.attr(v.replace(/[. ]/g, '-')) || opts[v];
});
if(opts.instance === "csdn_note") {
$('\
').insertBefore(script);
}
$('\
').insertBefore(script).hide();
window[opts.instance] = new csdn.note(opts);
})(window.jQuery, window);