/**
* 填充this.Dom,建立必要的背景iframe
* 注意:此时css尚未加载,所以样式都没生效
*/
getDoms: function() {
var wrap = this.Dom.wrap = this.conf.wrap
, tip = wrap.next()
;
if(!tip.is('.csdn_notice_tip')) {
tip = $('.csdn_notice_tip');
}
this.Dom.tip = tip;
this.Dom.btn = this.conf.btn;
wrap.append('<iframe src="about:block" frameborder="0" allowTransparency="true" style="z-index:-1;position:absolute;top:0;left:0;width:100%;height:100%;background:transparent"></iframe>');
return this;
},
resetPosition: function () {
var self = this
, offset = self.Dom.btn.offset()
;
self.Dom.wrap.css({
left: offset.left - 215 + 'px',
top: offset.top + 20 + 'px'
});
self.Dom.tip.css({
left: offset.left - 72 + 'px',
top: offset.top + 18 + 'px'
});
},
changeToNickname: function (ctx) {
var self = this;
ctx = ctx || self.Dom.wrap;
var users = $('.user_name', ctx).filter(function(){
return !$(this).data('nickname');
});
if(users[0]) {
$.getJSON('//api.csdn.net/service/open/nick?callback=?', {
users: users.map(function(){ return this.innerHTML; }).get().join()
}, function(data){
//
users.each(function (i) {
this.innerHTML = data[i].n;
$(this).data('nickname', true);
});
});
}
},
addEvent: function() {
var self = this
, unreads = -1
, hasReadedItems = false
, keepUnread = false
, notifications
;
self.initPanel();
notifications = $('.notifications', self.Dom.wrap); self.Dom.btn.click(function(e, params) {
if(self.Dom.wrap.toggle().is(':visible')) {
self.Dom.tip.hide();
self.emit('panel_showed', params);
} else {
self.emit('tip_showing');
}
return false;
});
$(window).resize(function(e){
self.resetPosition();
});
$(document).click(function(e) {
var t = e.target;
try {
if(!$.contains(self.Dom.wrap[0], t) && !$.contains(self.Dom.tip[0], t)) {
$('.close', self.Dom.wrap).trigger('click');
}
} catch(e) {
log(e);
}
}); $('.notice_list_con .notice_content', self.Dom.wrap).bind('click', function (e) {
var target = e.target
, item = $(target).parents(".list")
, index = item.index()
, detail = $('.detail_con .notice_content > *:eq(' + index + ')', self.Dom.wrap)
; item.removeClass('unread');
detail.addClass('curr').show().siblings().removeClass('curr').hide();
if(!item.hasClass("noslide")){
self.goSlide(notifications.eq(0), notifications.eq(1), 'right').emit('detail_showed', [detail, index]);
}
if(item.hasClass("action")&&target.tagName=="A"){
console.log("actions");
self.doaction({
id:$(item).attr("data-ids")*1,
dataApi:$(".callback",item).attr("data-api"),
args:$(target).attr("data-api")
},function(err, data){
$(".callback",item).html(data.msg);
$(".callback",detail).html(data.msg);
});
}
});三楼还有
* 填充this.Dom,建立必要的背景iframe
* 注意:此时css尚未加载,所以样式都没生效
*/
getDoms: function() {
var wrap = this.Dom.wrap = this.conf.wrap
, tip = wrap.next()
;
if(!tip.is('.csdn_notice_tip')) {
tip = $('.csdn_notice_tip');
}
this.Dom.tip = tip;
this.Dom.btn = this.conf.btn;
wrap.append('<iframe src="about:block" frameborder="0" allowTransparency="true" style="z-index:-1;position:absolute;top:0;left:0;width:100%;height:100%;background:transparent"></iframe>');
return this;
},
resetPosition: function () {
var self = this
, offset = self.Dom.btn.offset()
;
self.Dom.wrap.css({
left: offset.left - 215 + 'px',
top: offset.top + 20 + 'px'
});
self.Dom.tip.css({
left: offset.left - 72 + 'px',
top: offset.top + 18 + 'px'
});
},
changeToNickname: function (ctx) {
var self = this;
ctx = ctx || self.Dom.wrap;
var users = $('.user_name', ctx).filter(function(){
return !$(this).data('nickname');
});
if(users[0]) {
$.getJSON('//api.csdn.net/service/open/nick?callback=?', {
users: users.map(function(){ return this.innerHTML; }).get().join()
}, function(data){
//
users.each(function (i) {
this.innerHTML = data[i].n;
$(this).data('nickname', true);
});
});
}
},
addEvent: function() {
var self = this
, unreads = -1
, hasReadedItems = false
, keepUnread = false
, notifications
;
self.initPanel();
notifications = $('.notifications', self.Dom.wrap); self.Dom.btn.click(function(e, params) {
if(self.Dom.wrap.toggle().is(':visible')) {
self.Dom.tip.hide();
self.emit('panel_showed', params);
} else {
self.emit('tip_showing');
}
return false;
});
$(window).resize(function(e){
self.resetPosition();
});
$(document).click(function(e) {
var t = e.target;
try {
if(!$.contains(self.Dom.wrap[0], t) && !$.contains(self.Dom.tip[0], t)) {
$('.close', self.Dom.wrap).trigger('click');
}
} catch(e) {
log(e);
}
}); $('.notice_list_con .notice_content', self.Dom.wrap).bind('click', function (e) {
var target = e.target
, item = $(target).parents(".list")
, index = item.index()
, detail = $('.detail_con .notice_content > *:eq(' + index + ')', self.Dom.wrap)
; item.removeClass('unread');
detail.addClass('curr').show().siblings().removeClass('curr').hide();
if(!item.hasClass("noslide")){
self.goSlide(notifications.eq(0), notifications.eq(1), 'right').emit('detail_showed', [detail, index]);
}
if(item.hasClass("action")&&target.tagName=="A"){
console.log("actions");
self.doaction({
id:$(item).attr("data-ids")*1,
dataApi:$(".callback",item).attr("data-api"),
args:$(target).attr("data-api")
},function(err, data){
$(".callback",item).html(data.msg);
$(".callback",detail).html(data.msg);
});
}
});三楼还有
$('.detail_con .notice_content', self.Dom.wrap).delegate('.item_title', 'click', function (e) {
var target = e.target
, item = $(target).parents(".detail_list")
, index = item.index()
, list = $('.notice_list_con .notice_content > *:eq(' + index + ')', self.Dom.wrap);
if(item.hasClass("action")&&target.tagName=="A"){
console.log("actions");
self.doaction({
id:$(item).attr("data-ids")*1,
dataApi:$(".callback",item).attr("data-api"),
args:$(target).attr("data-api")
},function(err, data){
$(".callback",item).html(data.msg);
$(".callback",list).html(data.msg);
});
}
});
$('.close', self.Dom.wrap).click(function () {
self.Dom.wrap.hide();
self.emit('tip_showing');
}); $('.go_back', self.Dom.wrap).click(function () {
self.goSlide(notifications.eq(1), notifications.eq(0), 'left');
self.emit('panel_showed');
}); $('.prvnote, .nextnote', self.Dom.wrap).click(function () {
var el = $(this);
if(el.hasClass('disabled')) return;
var form = $('.detail_con .notice_content .curr', self.Dom.wrap)
, to = form[el.hasClass('prvnote') ? 'prev' : 'next']()
, index = to.index()
;
if (~index) {
$('.notice_list_con .notice_content > *:eq(' + index + ')', self.Dom.wrap).removeClass('unread');
$([form[0], to[0]]).toggleClass('curr');
self.goSlide(form, to, el.hasClass('prvnote') ? 'left' : 'right').emit('detail_showed', [to, index]);
}
}); self.on('panel_showed', function (e, showDetail) {
var hasGet = false, unreadsData;
self.resetPosition();
// 显示面板内容
if (unreads !== 0) {
self.getUnreads(self.showListCbWrap(function (err, data, loading) {
unreads = 0;
unreadsData = data.data;
}));
hasGet = true;
}
if (!hasReadedItems) {
$('.notice_content', self.Dom.wrap).empty();
self.getAllReaded(self.showListCbWrap(function (err, data, loading) {
hasReadedItems = true;
}));
hasGet = true;
}
if (hasGet) {
self.Dom.wrap.one('list_showed', function (e, err) {
if (err) {
self.error(err);
} else {
if(showDetail) {
var unreadsItem = $('.notice_list_con .unread', self.Dom.wrap);
if(unreadsItem.length === 1) {
unreadsItem.trigger('click');
}
}
if (unreadsData && unreadsData.length > 0) {
keepUnread = true;
setTimeout(function() {
self.setReaded(unreadsData);
}, 1000);
}
}
});
}
}).on('detail_showed', function (e, detail, index) {
// 显示通知详情
$('.detail_con .prvnote', self.Dom.wrap).toggleClass('disabled', !(index > 0));
$('.detail_con .nextnote', self.Dom.wrap).toggleClass('disabled', !detail.next()[0]);
if (!detail.data('loaded') && !$('dd', detail)[0] && !$('.empty:visible', detail)[0] && !$('.loading:visible', detail)[0]) {
self.getDetail(detail);
}
}).on('tip_showing', function () {
keepUnread = false;
if ($('.notice_list_con', self.Dom.wrap).css('display') !== 'none') {
$('.notice_list_con .notice_content .unread', self.Dom.wrap).removeClass('unread');
}
if (unreads > 0) {
self.resetPosition();
$('strong', self.Dom.tip.show()).html(unreads);
}
}).on('receive_unreads', function (e, data) {
// 收到未读消息实时通知 typeof data === number
unreads = (unreads === -1 ? 0 : unreads) + data;
if (self.Dom.wrap.is(':visible')) {
if($('.notice_list_con', self.Dom.wrap).is(':visible')){
self.emit('panel_showed');
}
} else {
self.emit('tip_showing');
}
}).on('receive_setreaded', function (e, data) {
// 收到设置为已读实时通知 typeof data === array or number
if (keepUnread) {
} else { // TODO 如果焦点在当前浏览器窗口,什么都不做
// 非查看窗口收到已读通知时需要重置状态,以便再次打开时能正确显示通知
unreads = -1;
hasReadedItems = false;
}
var num = /*$.isArray(data) ? unreads - data.length : typeof data === 'number' ? data : */0;
if (num <= 0) {
num = 0;
self.Dom.tip.hide();
}
$('strong', self.Dom.tip).html(num);
}); $('.close2', self.Dom.tip).click(function () {
self.Dom.tip.hide();
self.setReaded([], function(){
});
}); $('.tip_text', self.Dom.tip).click(function () {
self.Dom.btn.trigger('click'
// , ['Show one and only unread detail'] // 点击未读消息提示框后,如果未读条目只有一条,则自动进入哪一条未读
);
}); return self;
},
initPanel: function () {
$('.box', this.Dom.wrap).append('\
<div class="notifications notice_list_con curr">\
<a href="javascript:void 0" class="close"></a>\
<div class="menu_title">\
<span class="title"><a href="' + this.conf.app + '/" target="_blank" class="go_all">查看所有通知</a></span>\
</div>\
<div class="loading"></div>\
<div class="empty">暂没有新通知</div>\
<div class="notice_content"></div>\
</div>\
<div class="notifications detail_con" style="display: none">\
<div class="menu_title">\
<span class="title">\
<a class="go_back" href="javascript:void 0;">返回通知列表</a>\
<a class="notifications_page_none nextnote" href="javascript:void 0;">下一条</a>\
<a class="notifications_page prvnote" href="javascript:void 0;">上一条</a>\
</span>\
</div>\
<div class="notice_content"></div>\
</div>\
<div class="error"></div>');
},
fillList: function(insert, data) {
if(!data || !data.data || !data.data.length) return;
data = data.data;
var self = this
, wrap = self.Dom.wrap
, list = new Array(data.length)
, details = new Array(data.length)
;
$.each(data, function (i, v) {
console.log("v",v.isaction);
var action = v.isaction?" action ":"";
var isslide = !v.isslide?" noslide ":"";
var dataIds=v.containIds[0]*1;
list[i] = '\
<dl data-ids="'+dataIds+'" class="list rev_type'+v.type + (insert === 'append' ? '' : ' unread')+isslide+action+'" style="display: none">\
<dt>\
<i></i>\
<span class="item_title">' + v.title + '</span>\
<span class="count_down">' + v.time + '</span>\
</dt>\
</dl>';
var remain = v.containIds.length - self.conf.subCount;
details[i]='\
<div style="display: none">\
<dl class="detail_list rev_type' + v.type +isslide+action+ '" data-ids="' + v.containIds.join() + '">\
<dt>\
<i></i>\
<span class="item_title">' + self.ubbDecode(v.longTitle) + '</span>\
<span class="count_down"></span>\
</dt>\
</dl>\
<div class="loading"></div>\
<div class="empty">暂没有新通知</div>\
<a class="notifications_more" target="_blank">查看其它 0 条</a>\
</div>';
});
$('.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);
});
},
setReaded: function (data) {
var self = this;
self.invokeAPI('/set_readed?jsonpcallback=?', {
ids: $.map(data, function (i) {
return i.containIds.join();
}).join()
}, {
loading: false
});
},
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);
}
});
}
},五楼还有