12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031 |
- (function(window, undefined) {
- var protocol = window.location.protocol;
- var localUreadData=[],hasNewMsg=false,hasGetData=false;
- var defaults = {
- realtime: protocol+'//s{0}-im-notify.csdn.net'
- , api: protocol+'//svc-notify.csdn.net'
- , app:'http://msg.csdn.net'
- , space: protocol+'//my.csdn.net/'
- , count: 5
- , subCount: 5
- , staticUrl: protocol+'//csdnimg.cn/rabbit/notev2/'
- , cssUrl: 'css/style.css'
- , 'realtime.js': 'js/realtime.js' // base staticUrl
- // , 'channel': 'message'
- , 'socket.io.js': 'js/socket.io.js'
- // , 'socket.io options': { transports: ["xhr-polling", "jsonp-polling"]}
- }
- //
- , csdn = window.csdn || (window.csdn = {})
- , isShowMsg = true
- // && location.search === '?smsg=1' // DEV
- , friendlyErrors = {
- 'timeout': '请求超时,请检查网络后重试!'
- , 'abort': '请求被中止!'
- , 'parsererror': '解析错误,请检查网络后重试!'
- , 'No id supplied': '未登录或登录超时,请重新登录!'
- , 'locked': ''
- }
- ;
- var getCookie =function (objName){//获取指定名称的cookie的值
- var arrStr = document.cookie.split("; ");
- for(var i = 0;i < arrStr.length;i ++){
- var temp = arrStr[i].split("=");
- if(temp[0] == objName) return decodeURI(temp[1]);
- }
- }
- //
- if (Function.prototype.bind === undefined) {
- Function.prototype.bind = function (ctx) {
- var self = this;
- return function () {
- self.apply(ctx, [].slice(arguments, 0));
- };
- };
- }
- function log() {
- if (typeof console !== 'undefined') {
- Function.prototype.apply.call(console.log, console, Array.prototype.slice.call(arguments));
- }
- }
- var $
- , currUser = { username: '' } //登录用户对象
- ;
- csdn.note = function(conf) {
- $ = jQuery;
- //配置项
- this.conf = conf;
- //Dom节点
- this.Dom = {};
- //初始化
- this.init();
- };
- csdn.note.prototype = {
- /*
- * 【初始化入口】
- */
- init: function() {
- var self = this, opts = self.conf;
- opts.wrap = $('#' + opts.wrapId);
- if(typeof opts.count === 'string') {
- opts.count = parseInt(opts.count, 10) || undefined;
- }
- if(typeof opts.subCount === 'string') {
- opts.subCount = parseInt(opts.subCount, 10) || undefined;
- }
-
- self.conf = $.extend({}, defaults,
- //
- opts);
- //初始化消息列表
- self.getDoms();
- //检查用户登录
- self.checkLogin(function(data) {
- //
- if(isShowMsg) {
- //加载样式与事件
- self.loadCss(self.staticUrl(self.conf.cssUrl));
- self.addEvent();
- }
- // 初始化实时系统
- self.initRealtime();
- });
- },
- loadCss : function(src, callback){
- $('<link rel="stylesheet" type="text/css"/>').appendTo('head:first').load(function(){
- callback && callback();
- }).attr('href', src);
- },
- /**
- * 显示指定范围的.loading元素,返回一个函数,执行后将隐藏loading
- * @param {String} [selector=''] css选择器,配合ctx决定使用哪个.loading
- * @param {jQuery Object} ctx=wrap .loading所在的上下文
- * @return {Function(Function(Boolean loading) doneCallback)}
- * 隐藏已显示的.loading元素,并在隐藏完毕后调用doneCallback
- * loading参数用于指示.loading当前还在显示中(共享loading时会有这种状况)
- */
- loading: function (selector, ctx) {
- var self = this
- , ctx = typeof selector === 'object' ? selector : self.Dom.wrap
- , selector = typeof selector === 'string' ? selector : ''
- , el = $(selector + ' .loading', ctx)
- , num = (el.data('loadingCount') || 0) + 1
- , completed = false
- ;
- el.show().data('loadingCount', num);
- return function (callback) {
- if(completed) return;
- num = el.data('loadingCount') - 1;
- if(num <= 0) {
- num = 0;
- el.fadeOut('fast', function(){
- el.hide(); // jQuery 1.4.3存在的bug,当fadeOut元素的父元素不可视时,fadeOut不会改变元素display
- callback && callback(false);
- });
- } else {
- callback && callback(true);
- }
- el.data('loadingCount', num);
- completed = true;
- }
- },
- emptyCb: function () {},
- wrapCb: function () {
- var args = [].slice.call(arguments, 0);
- return function (callback) {
- callback && callback.apply(args);
- };
- },
- toggleEmpty: function (toggle, ctx, list) {
- ctx = typeof ctx === 'string' ? $(ctx, this.Dom.wrap) : ctx;
- $('.empty', ctx).toggle(toggle && !$(list, ctx)[0]);
- },
- staticUrl: function (url) {
- // TODO 可配置不同url使用不同时间戳
- return this.conf.staticUrl + url + '?4d63d1f';
- },
- on: function (type, data, handler) {
- this.Dom.wrap.bind(type, data, handler);
- return this;
- },
- emit: function (type, params) {
- this.Dom.wrap.triggerHandler(type, params)
- return this;
- },
- lock: function (id, callback) {
- var self = this;
- if(self.lockers === undefined) {
- self.lockers = {};
- }
- if(!id || !self.lockers[id]) { // id为null 空白字符串等表示不使用lock
- self.lockers[id || ''] = true;
- callback(null, function () {
- self.lockers[id || ''] = false;
- });
- } else {
- callback('locked', self.emptyCb);
- }
- },
- /**
- * 填充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 - 212 + 'px',
- top: offset.top + 25 + '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.unreads = unreads;
- self.initPanel();
- notifications = $('.notifications', self.Dom.wrap);
- self.Dom.btn.click(function(e, params) {
- self.emit('panel_showed', params);
- if(self.Dom.wrap.toggle().is(':visible')) {
- self.Dom.tip.hide();
- } 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)) {
- $(document).trigger('notify-hide');
- }
- } 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.hasClass("unread")&&self.setReaded([{containIds:item.attr("data-ids").split(",")}],function(data){
- keepUnread = true;
- item.removeClass('unread');
- //去除已读id
- var _strReadedIds = item.attr("data-ids");
- var _unread = [],_item={};
- for(var i=0;i<localUreadData.length;i++){
- _item = localUreadData[i];
- if(_item.containIds.join() === _strReadedIds){
- localUreadData.splice(i,1);
- }
- }
- self.emit('tip_showing');
- });
- 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"){
- self.doaction({
- id:$(item).attr("data-ids").split(",")[0]*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"){
- self.doaction({
- id:$(item).attr("data-ids").split(",")[0]*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);
- });
- }
- });
- //当trigger click时,会将事件源对象变成这个close节点,扰乱了其它js的判断逻辑。
- function hidecb(){
- self.Dom.wrap.hide();
- self.emit('tip_showing');
- }
- $(document).bind("notify-hide",function(){
- hidecb();
- });
- $('.csdn_note .close1', self.Dom.wrap).click(function () {
- hidecb();
- });
- $('.go_back', self.Dom.wrap).click(function () {
- self.goSlide(notifications.eq(1), notifications.eq(0), 'left');
- self.emit('panel_showed');
- });
- $('.read_all', self.Dom.wrap).click(function () {
- self.setAllReaded();
- return false;
- });
- $('.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) {
- self.resetPosition();
- if (!hasReadedItems) {
- $('.notice_content', self.Dom.wrap).empty();
- self.getAllReaded(self.showListCbWrap(function (err, data, loading) {
- hasReadedItems = true;
- }));
- }
- if(showDetail&&showDetail.data){
- self.fillList("prepend",showDetail);
- self.slideReset();
- hasGetData = true;
- hasNewMsg = false;
- }
- // 显示面板内容
- else if (localUreadData.length > 0&&hasNewMsg) {
- hasNewMsg = false;
- self.getUnreads(self.showListCbWrap(function (err, data, loading) {
- localUreadData = data.data;
- hasNewMsg = false;
- self.emit('tip_showing');
- }));
- }
-
- if (hasGetData) {
- 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');
- }
- }
- }
- });
- }
- }).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 = true;
- // if ($('.notice_list_con', self.Dom.wrap).css('display') !== 'none') {
- // $('.notice_list_con .notice_content .unread', self.Dom.wrap).removeClass('unread');
- // }
- self.initBtn();
- if (localUreadData.length > 0) {
- self.resetPosition();
- $('strong', self.Dom.tip.show()).html(localUreadData.length);
- $('.icon-hasnotes',self.Dom.btn).show();
- //派发给toolbar
- }else{
- $('.icon-hasnotes',self.Dom.btn).hide();
- }
- $(document).trigger("toolbar-setNotesNum",localUreadData.length);
- }).on('receive_unreads', function (e, data) {
-
- data.initUnreadIds&&(localUreadData = data.initUnreadIds);
- // 收到未读消息实时通知 typeof data === number123123
- //data.realtimeMsg&&localUreadData = data.realtimeMsg;
- //self.unreads = unreads = (unreads === -1 ? 0 : unreads) + data;
- if (self.Dom.wrap.is(':visible')) {
- if($('.notice_list_con', self.Dom.wrap).is(':visible')){
- if(data.realtimeMsg){
- self.emit('panel_showed',{
- data:data.data
- });
- }else{
- self.emit('panel_showed');
- }
- }
- } else {
- self.emit('tip_showing');
- }
- }).on('receive_setreaded', function (e, data) {
- var _len = localUreadData.length;
- // 收到设置为已读实时通知 typeof data === array or number
- if (keepUnread) {
- } else { // TODO 如果焦点在当前浏览器窗口,什么都不做
- // 非查看窗口收到已读通知时需要重置状态,以便再次打开时能正确显示通知
- self.unreads = _len;
- hasReadedItems = false;
- }
-
- if (_len <= 0) {
- self.Dom.tip.hide();
- $(".icon-hasnotes",self.Dom.btn).hide();
- }
- $('strong', self.Dom.tip).html(_len);
- });
- $('.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;
- },
- initBtn: function(){
- if(this.conf.btn.find(".icon-hasnotes").length<=0){
- this.conf.btn.html('<div class="icon-hasnotes" style="display:none"></div>');
- }
- },
- initPanel: function () {
- $('.box', this.Dom.wrap).append('\
- <div class="notifications notice_list_con curr">\
- <div class="menu_title">\
- <span class="title"><a href="' + this.conf.app + '/" target="_blank" class="read_all">全部设为已读</a><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) {
- var action = v.isaction?" action ":"";
- var isslide = !v.isslide?" noslide ":"";
- var dataIds=(function(){
- var _ids = [];
- for(var i=0,len=v.containIds.length,item=v.containIds;i<len;i++){
- _ids.push(item[i]*1);
- }
- return _ids.join(",");
- })();
- 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);
- });
- },
- 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], '<fieldset><legend>引用“<span class="user_name">' + m[1] + '</span>”的评论:</legend>' + replaceQuote(m[2]) + '</fieldset>');
- } 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, "回复<span class='user_name'>$1</span>:");
- content = content.replace(/\[url=([^\]]+)]([\s\S]*?)\[\/url\]/gi, '<a href="$1" target="_blank">$2</a>');
- content = content.replace(/\[img(=([^\]]+))?]([\s\S]*?)\[\/img\]/gi, '<img src="$3" style="max-width:200px;max-height:100px;" border="0" title="$2" />');
- content = content.replace(/\r?\n/ig, "<br />");
- 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 '<pre name="code2" class="' + m1 + '">' + _this.HTMLEncode(m2) + '</pre>';
- });
- content = content.replace(/(<br\s\S*>|<br>)/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, "'").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") {
- $('\
- <div id="note1" class="csdn_note" style="display:none; position:absolute; z-index:9999; width:440px">\
- <span class="notice_top_arrow"><span class="inner"></span></span>\
- <div class="box"></div>\
- </div>').insertBefore(script);
- }
- $('\
- <div class="csdn_notice_tip" style="display:none; position:absolute; z-index:9990; width:170px">\
- <iframe src="about:blank" frameborder="0" scrolling="no" style="z-index:-1;position:absolute;top:0;left:0;width:100%;height:100%;background:transparent"></iframe>\
- <div class="tip_text">您有<strong>0</strong>条新通知</div>\
- <a href="javascript:void 0" class="close2"></a>\
- </div>').insertBefore(script).hide();
- window[opts.instance] = new csdn.note(opts);
- })(window.jQuery, window);
|