Category: 未分类

  • WordPress Feed添加自定义内容的正确方法

    前段时间,Smashing Magazine的文章“10 Useful RSS-Tricks and Hacks For WordPress”第三条讲怎么在RSS Feed中插入任意内容。实际上该hack出自wprecipes,但是很遗憾,它已身在高墙外了。

    这种方法就是添加两个filter,分别在the_excerpt_rss和the_content_rss. 貌似合理,但实际上呢?且看wp-includes/feed-rss2.php的关键部分:

    [code lang=’php’]
    ]]>

    ]]>
    post_content ) > 0 ) : ?>
    ]]>

    ]]>

    [/code]

    首先鄙视一下RSS中只输出摘要的blogger,这样我们就只需关心外层if判断的else块了。Feed中的每个item都有一个description标签,调用的是the_excerpt_rss函数。而最重要的是content:encoded这个标签,因为多数RSS阅读器都是根据这里的内容显示的。可以看到,如果文章内容不为空——该条件99.9%的情况下成立,content:encoded的内容就是调用the_content. 该文件输出的是RSS 2.0格式,大部分WordPress blog的默认feed.

    再看feed-rss.php, feed-rdf.php和feed-atom.php,只有feed-rss.php输出的RSS 0.92格式的feed没有使用the_content. 因此,按照Smashing Magazine的方法,绝大多数情况下我们添加的内容不会再RSS阅读器中显示。

    所以正确的做法是把’the_content’也加上filter:

    [code lang=’php’]function process_feed($content) {
    if (is_feed()) { // 只在feed输出时处理,不影响站内内容显示
    $content = …;
    }
    return $content;
    }

    add_filter(‘the_content’, ‘process_feed’);[/code]

    最后看一下the_excerpt_rss这个函数到底都干了些什么。它定义在wp-includes/feed.php中,首先调用get_the_excerpt函数,然后应用hook到’the_excerpt_rss’的filter. get_the_excerpt定义在wp-includes/post-template.php中,取得文章的post_excerpt,然后应用hook到’get_the_excerpt’的filter,默认是wp-includes/formatting.php中的wp_trim_excerpt函数。它的作用是当post_excerpt为空的时候(该条件绝大多数情况下成立,我还没见过谁去写那个excerpt——默认在WP文章编辑器下方),取得文章内容,然后应用’the_content’的filter,再做一些去除tag的工作。总结:the_excerpt_rss就是取得the_content的输出,然后去除HTML标签。

    我们hook了’the_content’,所添加的内容,自然会进入the_excerpt_rss的输出(只是html tag被抹掉了),所以不要再hook ‘the_excerpt_rss’了,以免造成内容重复!当然对于那些有精力写excerpt的牛人另当别论。

    我目前的做法就是将处理函数hook到’the_content’和’the_content_rss’这两个上面。

    WordPress这部分现在似乎有点乱,不知道我有没有写错什么。如有错误,请指正,呵呵。

  • Get Recent Comments插件中文乱码问题

    前几天启用了Get Recent Comments这个插件,开始的时候一切正常,后来发现有时候中文会出现乱码。

    看了一下插件的源代码,发现它用wordwrap这个函数来把很长的单词切分开来。wordwrap函数没有multi-byte的版本,所以它就按字节来数,到了指定的地方就给野蛮地断开了。

    在以中文内容为主的blog里,我们基本不需要这个功能。那些超长的url可能会破坏布局,这时只需给外面的容器加上宽度并且overflow:hidden就可以了。无需修改插件源代码,最简单的做法是在该插件的选项页面把Wrap long words at这个选项设置成非常大的整数比如1000.

    写下文章标题的时候才去搜索,发现已经有人做了个“中文改良版”,呵呵。

  • Google Reader 可以实时更新feed

    大部分在线RSS阅读器都支持XML-RPC ping,不过国内的抓虾、鲜果似乎实际上都不管用。鲜果在feed上右键-反馈,点击马上更新,它才会真正地去抓取。网上有些人说ping了Google blog search,Google reader就随之更新,我没有找到确切的证据。

    不过Google Reader的阅读区上方有一个“Refresh”按钮,点击它之后,Google就会马上抓取最新的feed过来,不像鲜果这样的是放入一个队列,可能几分钟之后才能抓回来,这点从侧面反映了Google服务器阵容的强大。

    看了一下点击Refresh之后发送的Ajax请求,主要的url就是:

    https://www.google.com/reader/api/0/stream/contents/feed/http%3A%2F%2Fqingbo.org%2Ffeed?refresh=true

    即blog有新文章之后,在浏览器中访问该链接即可使Google Reader更新你的feed,在Google reader里订阅该feed的读者也就看到最新的了,不用等待Google Reader的默认更新周期。其实可以自动化一点,发布文章的时候让wordpress自动去请求该url,或者……不知道放在自动ping的列表里有没有作用,鉴于Google Reader更新的频率已经够快,我就懒得尝试了。

    在发布后修改文章的时候,刷新一下Google reader比较好,这样可以让它马上获取更新后的版本。

  • JavaScript 慎用 with

    像我这样最初并不是系统学习JavaScript的人,看到with这个东西的第一感觉是兴奋——不用再重复地写“element.style.xxx = …”了,只需要

    [code lang=’javascript’]with (element.style) {
    xxx = …;
    yyy = …;

    }[/code]

    但是作为解释型语言,JavaScript都需要在运行时来决定xxx/yyy到底是什么东西。对每一个名字(不仅仅是被赋值的,也包括读取的变量!)它会首先去在with括号里的对象的属性里去寻找,然后才会找局部变量,最后是全局变量。在JavaScript的虚拟机、JIT技术普及之前,这种性能问题需要非常的注意。

    正确的做法是给element.style做一个local variable的cache:

    [code lang=’javascript’]var es = element.style;
    es.xxx = …;
    es.yyy = …;
    …[/code]

    这样不仅相对减少了代码大小,同时性能上也比element.style.xxx = … 要好得多。

  • 为WordPress 2.7加上鼓励评论功能

    encouraged-commentary
    Jim Jeffers刚刚发布了他的encouraged commentary脚本,功能非常强大,罗列一些主要的:

    • 在文章中选中一段文字即可在留言中引用
    • 在某条留言中选中一段文字可引用,并且针对该条留言回复
    • 回复留言
    • 列出某留言的所有回复
    • 列出某评论者在该文章的所有留言

    在我看来,第一条是最基本的功能也是最重要的。最后两点,对于评论不是太多的blog来说基本是多余,甚至会显得很杂乱。

    而WordPress从2.7版本开始内置了对评论回复的支持,因此第二点、第三点也就没太大意义了。

    Jim Jeffers说不打算做任何插件,只在github上给出了源代码以及详细的实现步骤,不仅针对WordPress,大部分的blog平台都可以应用。

    我就针对WordPress 2.7,简化一下脚本和整个流程,下面是让一个主题支持encouraged commentary的步骤:

    1. 将需要的三个JavaScript脚本放在主题的scripts子目录中,保持主题结构清晰。因为只留下上面所列出的第一条功能,所以Jim Jeffers的脚本大大简化——这个压缩包里的是我简化过的。
    2. 在header.php中,引入需要的脚本:
      [code lang=’php’]



      [/code]

      注意不要使用wp_enqueue_script(’jquery’),它没有提供$函数,而Jim Jeffers用到了。

    3. 在single.php中,找到调用the_content函数的地方,把这个调用包在一个div中。例如:
      [code lang=’php’]

      Read the rest of this entry »

      ‘); ?>

      [/code]

    4. 现在,选中文章中的文字之后,就会浮出一个按钮”Respond”,可惜没有样式。我们现在需要给它和评论中的blockquote加上样式,我的仅作参考:
      [code lang=’css’]#comment-respond {
      width: 96px;
      height: 24px;
      background: transparent url(images/button.gif) left top no-repeat;
      color: #FFFFFF;
      border: none;
      font-family: sans-serif;
      font-size: 20px;
      font-weight: bold;
      vertical-align: middle;
      cursor: pointer;
      }

      ol.commentlist blockquote {
      margin: 0 0 0 20px;
      padding-left: 10px;
      background: transparent url(images/blue-vline.gif) repeat-y scroll left top;
      font-style: italic;
      }[/code]

    还有什么问题?现在就在这篇文章试试这个功能吧!

  • JavaScript simple dialog

    dialog
    前些天做了一个非常简单的JavaScript library,用来模拟模态对话框(modal dialog),刚刚放到Google code上:javascript-simple-dialog

    在一个页面上向用户提示信息、与用户交互有多种方式,最基本的办法就是window的alertprompt函数。不过alert弹出的同时,会有一声比较恐怖的提示音,prompt在某些浏览器里因为安全限制比较麻烦,用户体验都不是太好。

    以前做项目的时候也想找一个现成的对话框来用,但是大部分都不符合我的要求,比如jQuery的插件SimpleModal只能允许同时有一个对话框。jQueryUI的Dialog,当时我记得结构比较复杂,使用的CSS定位比较特殊,对内部内容要求也比较特殊,不知道现在的最新版本怎么样。

    于是这次基本是从自己的需求出发,设计并实现了这么一个小东西。最主要的特性是兼容IE(即可以盖住页面上的select按钮——掩饰IE臭名昭著的bug),以及可同时运行多个实例。

    更多请看Google code上的项目主页,在那里也可以下载代码或者直接从svn check out.

    这里有一个简单的demo.

  • 主题支持2.7评论系统需要注意的几点

    评论支持嵌套和分页是WordPress 2.7的一大亮点,不过让主题支持这个新的评论系统稍微有点麻烦,WordPress Codex上给出了一长串步骤

    其实最简单的,就是仿照默认主题来做,这里有一篇中文的文章讲得很清楚。

    需要注意的是:第三步尤其重要,很多人可能会忘记还要修改header.php,但是如果没有加入这个JavaScript脚本,点击回复就会刷新页面,用户体验很糟糕。

    另外如果要做一个通用的主题,就必须支持分页。仿照默认主题,就是下面的代码:

    [code lang=’php’]

    [/code]

    然而2.7的next_comments_link函数有点问题,在后台启用分页的时候,一切正常。但是禁用分页以后,next_comments_link无论如何都会返回一个链接!这一点用默认主题就可以测试,禁用分页之后,在评论列表的最下方可以看到链接“Newer comments”。我已经在trac里提交了一个bug,希望在下一个版本可以解决。

    目前的解决办法是在主题中判断一下page_comments选项,启用时,才生成导航链接:

    [code lang=’php’]

    [/code]

    我的主题是给自己用的,干脆就直接不生成导航了,因为我现在不打算分页。

  • Firebug 1.3与Ajax response

    如果一个Web开发者从来不使用firebug甚至从未听说过,我真替他感到可悲。

    昨天,Firebug 1.3正式发布release notes在Google code上可以看到,现在查找更新即可自动升级了。Firebug是Firefox的扩展,但是它本身也提供了良好的接口,已经有不少扩展了。1.3版本包含了一些对于扩展开发者非常有帮助的特性,然而对于我们普通的Web开发者用户,最期待的更新当属JavaScript debugger了。在一个inner function里单步的时候,你可以通过scope chain来查看function定义同级的变量值。

    在调试Ajax应用的时候,用Firebug来查看Ajax请求的response即服务器端返回的响应是最方便的,省了使用HTTP抓包工具。然而从某个时间开始,Firebug的这一功能不再好用了,由于Firefox的一个内部实现问题,插件无法对响应进行分析。从这个讨论来看,应该是2.0版本,不过我记忆中似乎没这么早……症状就是,在console的Ajax请求列表中查看一个的时候,response里并不是服务器返回的数据,而是Firebug的一个提示,具体请看这个网页的第一张图片。要想看到response,Firebug必须重新发送这个请求,这在许多情况下是不现实的。

    看到Firebug 1.3发布,我就在console栏里测试了一下Ajax的请求,惊喜地发现response已经可以查看了。

    事实上能否查看response数据在于Firefox而不在于Firebug,所以Firebug新版本发布与之关系不是很大。在前面提到的图片中可以看到,Firebug给出了一个链接,指向一个proposal:

    new nsHttpChannel interface to allow examination of HTTP data before it is passed to the channel’s creator

    等这个proposal被实现,查看Ajax response的功能自然就恢复了。从该bug记录下面的评论来看,应该是在3.0.4版本就实现了。再看3.0.4修正的bug列表,果然430155就在里面。

    好久没有调试Ajax应用了,这个功能的恢复还是挺好的。

  • Blog全新改版——白板

    白板,开会、讨论用的白板。要是麻将里的白板,那下一个主题就是红中了。

    主题中用到图片的地方,就尽量模仿成白板上写字的效果。似乎专业的美工做的时候,都是先把整个页面画出来,然后再切割,实现。我很不专业,先是日思夜想,把整个页面画在脑子里,然后就开始实现。

    首先画出页面的边框(白板的框架),CSS里就写出header, content, sidebar和footer了。然后就盯着首页,把日志的样式调出来,sidebar的样式,接着把原来主题里的评论样式复制过来改改颜色,中间需要什么图片就随时画(不排除“窃”)。

    最后就是最重要的header了。领导亲笔题词,给我开了个好头,让我的心里充满希望:

    星月轮转 (by qingbo)

    中间用bittbox做的免费白板字体弄了个类似tag cloud的文字组合,右边是一列订阅按钮。tag cloud里本来没有”RSS”的,后来加上订阅按钮以后,灵机一动,加了个”RSS”,又连了个箭头。一个全新的主题,就这样诞生了。

    当然,不可避免地要加上“增强WordPress中的Gravatar应用”一文中介绍的小trick 🙂 接下来,慢慢地加一些实用的插件,改善用户体验。

    在做主题的过程中,免不了又跟IE死磕一番。中间也巩固了不少知识,正所谓——越磨砺,越光芒。这些知识都是伟大的IE创造的。有那么两三刻,我都想在主题里针对IE用户放出一个banner:“我谨代表全世界受苦受难的劳苦大众,请求你弃暗投明,放弃史前怪物,使用非IE浏览器。”后来一想,我还得为了这个banner在IE里正常显示而折腾,算了,有空再说吧。

    欢迎测试、指正。

  • 延迟发布Feed须谨慎

    前阵子有人分享了一个延迟发布feed的技巧,在WordPress用户间广为流传。其原理就是利用WordPress的filter机制,发现当前的请求是Feed,即在查询条件中加一条,限制post的发布时间为五分钟之前(原文的代码escape太厉害了,直接复制有错误):

    [code lang=’php’] /**
    * puplish the content in the feed later
    * $where ist default-var in WordPress (wp-includes/query.php)
    * This function an a SQL-syntax
    */
    function publish_later_on_feed($where) {
    global $wpdb;

    if ( is_feed() ) {
    // timestamp in WP-format
    $now = gmdate(‘Y-m-d H:i:s’);

    // value for wait; + device
    $wait = ‘5’; // integer

    // http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html#function_timestampdiff
    $device = ‘MINUTE’; //MINUTE, HOUR, DAY, WEEK, MONTH, YEAR

    // add SQL-sytax to default $where
    $where .= ” AND TIMESTAMPDIFF($device, $wpdb->posts.post_date_gmt, ‘$now’) > $wait “;
    }
    return $where;
    }

    add_filter(‘posts_where’, ‘publish_later_on_feed’);
    ?>[/code]

    当时我看到之后也很兴奋,觉得非常之有用。因为我就经常在发布一篇文章之后马上发现有错误或者遗漏,赶紧修改,但是此时可能已经有些RSS reader过来抓取过了,我所做的修改不一定能被Feed订阅者收到(Atom Feed应该可以)。

    不过当我加上这个功能,又写了一篇文章之后,发现了问题。在文章发布的时候,WordPress会向预定的一些服务器发送ping,通知它们这里有更新,赶紧来抓取。如果该服务器反应很迅速,糟了,它来抓取RSS的时候,发现并没有新的文章——被放鸽子了。它可不知道要等五分钟再来抓取,新文章只好经历漫长的等待才能被抓到。

    所以要保证文章少出错,还得在发布之前多预览,多检查,而延迟发布RSS只能让你点击Publish按钮的时候更加勇猛。使用这个技巧一定要三思而后行

    为什么发布的时候发送ping消息很重要呢?如果不这样,那些RSS Reader只能盲目地周期性来查看,比如每天一次或者每隔3小时一次,Feed托管服务商也是这样。而在发布的同时通知它们,它们就会确切地知道你的blog有更新了,很快就会过来抓取,读者也就能在第一时间看到你的新文章了。

    附带列一下我的Update Services列表:
    http://rpc.pingomatic.com/
    http://ping.feedburner.com/
    http://www.zhuaxia.com/rpc/server.php
    http://www.xianguo.com/xmlrpc/ping.php
    http://blogsearch.google.com/ping/RPC2
    http://blog.youdao.com/ping/RPC2

    如果你使用feedsky的服务,当然也要把它的ping server(http://www.feedsky.com/api/RPC2)加上。

    BANGEC852A4639967E2F93AD50BBXIANGUO
    BANG004B23D38B0F7BB089F9BDD4XIANGUO
    BANGE0FB3CE98688F38AFA7A9C4DXIANGUO