/**
     * 填充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);
          });
        }
      });三楼还有

解决方案 »

  1.   


          $('.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();
        },四楼还有
      

  2.   


        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);
              }
            });
          }
        },五楼还有