刘未鹏|C++的罗浮宫

Knowledge sharing is the best reuse

刘未鹏ID:pongba
[修改头像]
708172次访问,排名42好友7人,关注者64
pongba的文章
原创 99 篇
翻译 8 篇
转载 0 篇
评论 1514 篇
刘未鹏的公告
除非特别声明,本站采用Creative Commons License许可。转载请注明作者、出处,非商业。

喜欢这个Blog的风格?见这里这里,还有这里

我的豆瓣饭否

讨论问题请到TopLanguage小组

TopLanguage

gtalk/msn(邮件请发送到gmail邮箱)

pongba@gmail.com
pp_liu@msn.com

订阅C++的罗浮宫

  • FeedSky
  • 订阅到鲜果
  • 订阅到Google
  • 订阅到抓虾
  • 订阅到BlogLines
  • XML聚合

搜索C++的罗浮宫上的内容

最新发表

    whaz going on


    饭否

    books I've translated




    最近评论
    pongba:@dd:
    误会了,不是不想,而是CSDN Blog不支持全文RSS。
    以前有一阵子倒是开放了全文RSS,我也跟着调整成了全文输出,但过了一阵子,又给关掉了。
    其实CSDN BLOG大可在RSS里面放广告嘛
    dd:RSS不是全文输出,惯用Google Reader和其它阅读器的读者可能会感觉不方便。
    为什么不改成全文输出呢?是技术问题,还是你很在意页面的点击量?
    顺便赞你的blog,很久以前,在你blog的重点还是C++语言的奇技淫巧时就开始看。:)
    刘未鹏:@william:
    是的。不过这里只是说明一个一般性原则。所以有些条件(如函数一阶可导)就不加赘述了。
    williamxu:Good job!
    "譬如通过驻点来求函数的最值,我们通过考察函数的最值(除了函数边界点外),发现它必然有一个性质,即在这个点上函数的一阶导数为0"
    是否应该是函数在区间上连续可导才成立,除边界点外,如果函数最值点不连续,是没有导数的。
    ppzhupapa:Read了one遍,确实is好article,but楼主write文章的style我feel不太good,mainly是many没necessary用English的places都using英语,no idea我这样say,楼主if or not看得understand.
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes
    文章分类
    收藏
    相册
    其它图片
    文章中的图片
    我的大头贴
    C++
    Andrei Alexandrescu
    Andrew Lumsdaine
    Bjarne Stroustrup
    boost
    C++ Standard Commitee
    Doug Gregor
    Hans J. Boehm
    Jaakko Jarvi
    Jeremy G. Siek
    Matthew Wilson
    newsgroups
    boost.Developer
    boost.User
    comp.lang.c++.moderated
    comp.std.c++
    TopLanguage
    Open Source
    codeplex
    Google AJAX Search API
    Google Code Prettify
    Google Web Toolkit
    MS shared source initiative
    notepad++
    STLSoft
    不认识的朋友们
    fatalerror99
    Yelz
    余晟|乱象&乱想
    刘慈欣
    姬十三
    张志强|阅微堂
    许式伟
    阮一峰
    鲍志云
    其它
    科学松鼠会
    科学美国人
    科幻世界
    认识的朋友们
    chenyufei
    duguguiyu|Venus神庙
    Joyfire
    littlestone
    lxwde
    Matrix67
    soloist
    云风
    刘江@图灵
    史晓明
    周星星
    周筠@博文视点
    孟岩
    张振
    徐宥|4G Spaces&Web 2.3
    方舟@博文视点
    李笑来|Pure Pleasure
    杨文博
    王信文|地球没有好朋友
    荣耀
    莫华枫
    袁泳(g9)|负暄琐话
    谢东升
    陈冀康@华章
    存档

    原创 Blog外挂之:热门文章与导航栏

    新一篇: Blog外挂之:文章置顶

    Blog外挂之:热门文章与导航栏

     

    By 刘未鹏

    C++的罗浮宫(http://blog.csdn.net/pongba)

     

    还是看图说话:-)

     

    图一:导航栏

     

    图二:热门文章

     

    导航栏的实现很容易:往mainheader之间塞入一个div,往div里面写入所有的分类链接即可。

     

    分类的获取有几个办法,一是把分类链接也收藏到del.icio.us上,这样就可以用JSON协议获取到所有分类(见上篇文章——Blog外挂之:妙用del.icio.us实现站内相关文章)。二是直接获取侧边栏上的分类列表。dodoblog上用的就是这个办法,但这个办法太脆弱,因为分类的那个ul没有id,所以用getElementById就行不通了。只能依赖于对那个ul的顺序的掌握,先getElementById(‘rightmenu’)获得rightmenu的引用,然后再对后者getElementsByTagName(‘ul’)获得其中所有的ul容器的数组,然后基于对页面代码的观察从这个数组中取出对应于分类菜单的ul。这个办法的问题在于如果我们不小心在公告栏加入了新的ul,或者能生成uljs代码,就会破坏分类那个ul所在的序号。另一方面,把分类链接收藏到del.icio.us上是个较好的选择,但del.icio.us帐号的空间有限,目前你最多能获取100post,还是别浪费在分类上的好。用另一个del.icio.us帐号的办法又会增加一个http请求。想想还是不要杀鸡用牛刀了。于是结果使用的是brute force,直接把分类链接及标题硬编码到代码中了:-)反正分类的修改也并不频繁。比如我的分类之前都快一年没改动了。

     

    导航栏实现的主要代码如下:

     

    function insertTopMenuDiv()

    {

      var topMenuDiv = document.createElement('div');

      topMenuDiv.setAttribute('id', 'topMenu');

     

      var main = document.getElementById('main');

      main.parentNode.insertBefore(topMenuDiv, main);

     

      return topMenuDiv;

    }

     

    function appendNavigatorBar()

    {

      var topMenuDiv = insertTopMenuDiv();

     

      var categoryList = getCategoryList();

     

      var html = '';

      for(var i = 0; i < categoryList.length; ++i){

        html += '<a href = "' + categoryList[i].url + '" class = "tab ';

        if(GetThisURL() != categoryList[i].url)

          html += 'tabUnselected">';

        else

          html += 'tabSelected">';

        html += categoryList[i].title;

        html += '</a>';

      }

      document.getElementById('topMenu').innerHTML = html;

    }

     

    getCategoryList你自己写。目的是获取分类列表。我用的是硬编码。

     

    CSS调整

    导航栏就这样插入到mainheader之间是不行的,需要调整格式。往后台定制CSS栏加入代码调整其位置,我的是:

     

    #topMenu {

      position:absolute;

      top: 78px;

      padding-left: 20px;

    }

     

    #topMenu a:hover {

      background: #0044BB none repeat scroll 0%;

      color: #FFFFFF;

      text-decoration: none;

    }

     

    .tabUnselected {

      border-left:1px solid #CCCCCC;

      border-right:1px solid #CCCCCC;

    }

     

    .tab {

      margin:0em 0em 0em 0.25em;

      padding:2px;

      font-size: 12pt;

    }

     

    .tabSelected {

      border-left:1px solid #CCCCCC;

      border-right:1px solid #CCCCCC;

    }

     

    最重要的就是topMenu的位置。我定的是离顶部78px。你自己用firebug调节吧。tabSelectedtabUnselectedCSS一样是因为原本的效果不能在IEfirefox下统一,只好暂时就这样了。Web设计达人自己调整就是了:-)俺是程序员,只能朴素一点,用左右两条线分隔了。

     

    热门文章的实现也不算复杂。最关键的问题是如何获取相应文章的评论数。我原本想通过blogrss文件获得,观察rss文件会发现里面包含了每篇文章的评论数。等等,我说了每篇文章吗?唉,其实只有聊聊十几篇而已,所以没法对整个blog上的所有文章进行排名了。不过rss可以用来实现最近更新

     

    图三:最近更新

     

    Anyway,那如何获取评论数呢?我们知道每篇文章的URL(从del.icio.us上获得的),问题转化为如何从URL到评论数。CSDN blog对文章的评论数是动态加载的:

     

    图四:加载中

    图五:加载完毕

    既然是动态加载的,那么必然有办法获取对应文章的评论数。偷窥一下页面代码:

     

    图六:评论加载代码(一)

     

    可见,每篇文章的postFoot处都有一个js调用,调用AddFeedbackCountStack将该文章的一个ID添加一下,这个ID其实就是文章URL的最后一部分。从数字大小猜测它应该是服务器上的文章编号,1601519,也就是第一百多万篇文章。随便找篇03年的文章,你会发现那时候CSDN blog系统上只有一万多篇文章。

     

    为了节省HTTP请求,CSDN blog的页面加载过程中并非每遇到一个“评论数(…)”框都发起一次http调用获取相应文章的评论数,而是用刚才你看到的AddFeedbackCountStack先将该文章的ID保存起来,等到最后一并获取所有的评论数:

     

    图七:评论加载代码(二)

     

    LoadFeedbackCount做了两件事情:先使用一路保存下来的文章ID列表来获取一个评论数列表。然后将评论数一一填充到相应的“评论数(…)”框中。如果一篇文章的ID1234那么其评论数框的span id就是FeedbackCount_1234。见图六。

     

    AddFeedbackCountStackLoadFeedbackCount的代码在LoadFeedbackCount.js中。自己看它是怎么发起http请求获取评论数的吧。

     

    最后需要注意的一点是,无论ID列表里面文章的顺序如何,返回的评论数列表总是对应于ID从大到小来排列的。也就是说如果你给出的ID列表为“ID2ID1,假定ID2 < ID1,即第二篇文章发得较早,那么返回的评论数仍然还是feedbackCountForID1feedbackCountForID2。所以如果del.icio.us上的文章收藏并非按从早到晚严格顺序排的,那得先sort一下,然后建立ID列表。

     

    知道了如何获取评论数就好办了,有了URL列表,有了相应的评论数。排名那就太简单了。

     

    最热门文章排行的主要代码如下:

     

    var getFeedbackCountReq;

    var myBlogPosts = [];

    var hotPostsContainer;

     

    function showHotPosts(ct)

    {

      hotPostsContainer = ct;

      for(i = 0; i < Delicious.posts.length; ++i){

    myBlogPosts.push(

    {url:Delicious.posts[i].u,

    id:urlToId(Delicious.posts[i].u),

    title:Delicious.posts[i].d, feedbackCount:0}

    );

      }

     

      myBlogPosts.sort(compareById);

     

      var idList = '';

      for(i = 0; i < myBlogPosts.length; ++i){

        idList += myBlogPosts[i].id + ',';

      }

     

      getFeedbackCountReq = HTTP.newRequest();

      getFeedbackCountReq.onreadystatechange =

    handleGetFeedbackCountReq;

      getFeedbackCountReq.open('GET',

    '/NewCount.aspx?FeedbackCountStack=' + idList);

      getFeedbackCountReq.send(null);

    }

     

    function handleGetFeedbackCountReq()

    {

      if(getFeedbackCountReq.readyState==4){

        if(getFeedbackCountReq.status==200){

          handleGetFeedbackCountReq2(

    getFeedbackCountReq.responseText);

        }

      }

    }

     

    function handleGetFeedbackCountReq2(feedbackStr)

    {

      var feedbackList = feedbackStr.split(',');

      var i;

      for(i = 0; i < myBlogPosts.length; ++i){

        myBlogPosts[i].feedbackCount = feedbackList[i];

      }

      myBlogPosts.sort(compareByFeedbackCount);

       

      var title = document.createElement('h3');

      title.appendChild(document.createTextNode('blog评论最多文章'));

      hotPostsContainer.appendChild(title);

     

      var NGList =

     ['http://blog.csdn.net/pongba/archive/2004/08/26/84978.aspx',

    'http://blog.csdn.net/pongba/archive/2004/11/26/195052.aspx',

    'http://blog.csdn.net/pongba/archive/2004/11/26/195075.aspx'];

     

      var maxNumHotPosts = 12 + NGList.length;

      if(myBlogPosts.length < maxNumHotPosts)

    maxNumHotPosts = myBlogPosts.length;

     

      var ul = document.createElement('ul');

      ul.setAttribute('id', 'my_hot_posts');

     

      for(i = 0; i < maxNumHotPosts; ++i){