2006-11-27

應用 JSON 實現「最新文章」、「最新回應」和「Blog 聯播」

之前在Blogger Buzz(Blogger.com的 Blog),看到一篇消息說 Blogger 支援 JSON,說實話我不知道那是啥(JSON = JavaScript Object Notation, 讓跨網站也可以讀取到的資料結構?!),不過有人實作出一些東西來,就知道這玩意的厲害了。

之前自己這篇提到如何利用 Feed 在 Blogger 裡加入最新文章和回應,但使用上有些限制,像是篇數(只允許五篇)還有格式內容,更新好像也不夠快,從小帽的 Blog 看到有利用 JSON 做出最新文章和回應的 Javascript,還可以做 Blog 聯播或是特定標籤的 Feed,這實在是太厲害了,因此參考兩位的文章也做出屬於自己的 Javascript,用來顯示最新回應、最新文章和 Blog 聯播。使用方法很簡單,只要在 Sidebar 的網頁元素(Page Elements)裡新增 HTML/JavaScript 程式碼,依自己的需求分別加入下面的元件,貼入程式碼就好了(紅色部分的程式碼要依個人設定和需求去更改,像有一行數字等於 10 代表的意思是要顯示十篇,另一個 temp 那行是表示顯示的內容和格式,可以自行修改)。

最新回應 (Recent Comments):

<div id="newComments">
  Loading...
  <noscript>failed!<br/>Javascript not supported here!</noscript>
</div>

<script>
function handleComments(json) {

  function compareentry(a,b) {
  order= Date.parse(a.published.$t.replace(/^(\d{4})-(\d{2})-(\d{2})T([0-9:]*)([.0-9]*)(.)(.*)$/, '$1/$2/$3 $4 GMT')) - Date.parse(b.published.$t.replace(/^(\d{4})-(\d{2})-(\d{2})T([0-9:]*)([.0-9]*)(.)(.*)$/, '$1/$2/$3 $4 GMT'));
  return 0-order;
  }

  var temp = '<ul>';
  var CommentShow = 10;
  var sortentry = json.feed.entry.sort(compareentry);
  for (var i=0, Comment; Comment = sortentry[i]; i++) {
    if (i >= CommentShow)
      break;
    var title=Comment.content.$t.substr(0,30);
    title=title.replace(new RegExp("BR","gm"), "");
    title=title.replace(new RegExp("</>","gm"), " ");
    var link=Comment.link[0].href.replace("#", "#comment-");
    var authorname=Comment.author[0].name.$t;
    var timestamp=Comment.published.$t.substr(0,10);
    temp += '<li><span class="item-title">'+authorname+': <a href="'+link+'">'+ title +'</a> - '+timestamp+'</span></li>';
  }
  temp+="</ul>";
  document.getElementById("newComments").innerHTML = temp;
}
</script>

<script src="/feeds/comments/default?alt=json-in-script&callback=handleComments" type="text/javascript"/></script>

至於最新文章 (Recent Posts) 的部分,同樣是用上面那段程式碼,有小地方部分要修改,Feed 的網址也要改:

<div id="newPosts">
  Loading...
  <noscript>failed!<br/>Javascript not supported here!</noscript>
</div>

<script>
function handlePosts(json) {

  function compareentry(a,b) {
    order= Date.parse(a.published.$t.replace(/^(\d{4})-(\d{2})-(\d{2})T([0-9:]*)([.0-9]*)(.)(.*)$/, '$1/$2/$3 $4 GMT')) - Date.parse(b.published.$t.replace(/^(\d{4})-(\d{2})-(\d{2})T([0-9:]*)([.0-9]*)(.)(.*)$/, '$1/$2/$3 $4 GMT'));
    return 0-order;
  }

  var temp = '<ul>';
  var PostShow = 10;
  var sortentry = json.feed.entry.sort(compareentry);
  for (var i=0, Post; Post = sortentry[i]; i++) {
    if (i >= PostShow)
      break;
    var title=Post.title.$t;
    var j=0;
    while (j < Post.link.length && Post.link[j].rel != "alternate")
      j++;
    var link=Post.link[j].href;
    var authorname=Post.author[0].name.$t;
    var timestamp=Post.published.$t.substr(0,10);
    temp += '<li><span class="item-title">'+authorname+': <a href="'+link+'">'+ title +'</a> - '+timestamp+'</span></li>';
  }
  temp+="</ul>";
  document.getElementById("newPosts").innerHTML = temp;
}
</script>

<script src="/feeds/posts/default?alt=json-in-script&callback=handlePosts" type="text/javascript">

不過如果是用來顯示自己 Blog 的最新文章,作者也只有自己一個人,那麼 authorname 的欄位也可以自己選擇要不要拿掉。

最後是所謂的 Blog 聯播 (Blogrolls)。說穿了,其實聯播就是在自己的 Blog 首頁顯示別人 Blog 的文章,訂閱別人的 Feed URL,只要改「最新文章」的倒數第二行,把 Blog Feed 網址改成對方的就行了。所以有了這招,可以取代掉 Blogger 本來內建的 Feed 模組(因為該模組限制訂閱五篇,又限制顯示的格式)。

另外,上面提到的都是處理整個 Blog 最新文章的 Feed,如果想要訂閱的是某分類標籤的所有文章,那麼該如何處置?一樣,只要在訂閱的 Feed URL 動手腳就行了,改成下面這樣:

<script src="http://聯播或你的Blog網址/feeds/posts/summary/-/標籤名稱/?alt=json-in- script&callback=handlePosts" type="text/javascript"></script>

作者有提到一個標籤加上 Feed 的妙用:將你要推薦、頂置或公告的文章都加上一個特定標籤,然後訂閱這個標籤的 Feed 顯示在 Blog 的元件裡,這樣你在首頁就可以有動態的頂置或是公告區囉!如果嫌上面的程式還要修改很麻煩,可以用原作者自己寫的「程式產生器」來產生自己的程式碼,以上的程式產生器請參閱參考文章裡的連結。

參考文章:
小帽Blogger 聯播程式產生器 - 增加「最新文章與最新回應」與「標籤訂閱」程式產生器
Blogger(Beta) 最新回應程式產生器
Blogger聯播程式產生器(PartII)
Blogger(Beta)最新文章與最新回應JavaScript Code Part II

[注意]:
在回答網友問題的過程中發現,以上實現「最新文章」和「最新回應」的方法,如果同時使用(就是裝兩個以上),當瀏覽器是 IE 的時候,因為裡面有兩套相同的 Javascript 原始碼,內容會錯亂導致只有一個內容出得來(Firefox 正常)。請記得更改裡面的一些定義(像是把 "newComments" 字串在不同模組裡用不同的名稱),或是把 Javascript 的函式統一搬到範本裡面,每個 Element 負責用不同的 Feed URL 呼叫它就行了,如果直接用我範例的程式碼直接貼多個模組出來,IE 是可能會錯亂的喔!

[8/28 更新]:
由於 Blogger 更改了回應 的 RSS Comment Feed 的格式,本來 Feed 裡 Title 欄位有資料,是部分的 Comment 文字,更改之後 Title 欄位是空白的,會導致拿 Feed 來做「最新回應」模組時回應內容不見。因此,「最新文章」可以抓 title 當標題,而「最新回應」就要抓內容 content 的部分字串來用(還要修正 link、取代不必要的換行符號)。

回應: 28

JAMESEE-ST-SMILE 提到...

life just good

Wylie 提到...

你好,參照你的最法完成了我BLOG上的最新回應,不過我遇到了一個問題,就是當我刪除文章後,那文章的意見好像不會跟著在最新回應上消失哩。而意見的連結也是失效的。煩你幫我看一下,謝謝你!

Abin 提到...

我檢查過了,沒錯,有這個問題:
當文章被刪除的時候,該文章的回應並不會一併被刪,而且,文章連結也會失效..
我有查一下 Feed,因為回應本身和本文是分開的,如果 Feed 裡面的內容不會一併被刪除,目前用 Feed 來取得最新回應的方法就會存在這個 bug,這是 blogger beta 的問題,並不是這個 hack 有問題..
怎麼解決呢?在 Feed 內容官方沒有修正之前無解,除非你在刪文前把回應都先殺掉,不然暫時沒辦法喔..
Blogger beta 果然還是 "beta" ..

Erich Chen 提到...

請問一下,要做Blog聯播,對象似乎一定要是Blogger beta上面的BLOG,我試著抓原先Blogger的站台資料似乎是不行的?
謝謝

Abin 提到...

是的,本文提到的方法是用 JSON 來實現最新文章和 Blog 聯播,目前只有 Blogger Beta 的 Feed 支援這種做法,舊的 Blogger 或其他 Blog 不行。
如果您想用舊的 Blogger 或是與其他 Blog 做聯播,請用這篇文章提到的,用網頁元素裡加入訂閱的元件,不過填入的 Feed 網址是其他網站的 Feed URL,同樣可以達到 Blog 連播的目的,而且,只要有提供 Feed 的都可以加入聯播喔!(只不過,數量限制只有五篇)

匿名 提到...

請問能夠在最新回應部份把部份留言改成標題嗎?

例如把

我檢查過了,沒錯,有這個問題:當文章被刪除的時候,該文章的回應並不會一併被刪,而且,文章連結也會失... - Abin @ 2006-12-05

改成

應用 JSON 實現「最新文章」、「最新回應」和「Blog 聯播」- Abin @ 2006-12-05

抱歉一直麻煩您 ^___^

Abin 提到...

這個 JSON 的方法,是透過 Javascript 過濾 Feed 的內容產生的,所以,顯示出來的結果,只限於 Feed 裡面有的。
你提到最新回應想要把「部分內容」改成原文的「標題」,那要看 Feed 裡面有沒有喔!
我檢查了一下Feed ,發現裡面的欄位,其中 post.title 是「回應的標題」,內容卻被寫入「部分內容」,也就是說,Feed 裡面的資料並沒有實際原文的標題,而被「部分內容」給取代(這是官方的 Feed 裡做出來的),裡面沒有的,這個方法就生不出來囉!
所以,現在就只能用那個「部分內容」當作「標題」,除非 Feed 裡有提供,不然這個方法改不出你說的效果喔!

Abin 提到...

啊!我發現了另外一種做法,可以提供更有彈性的「最新回應」,不過我還沒研究他的原始碼。看一下原作者的文章,看看右下他的最新回應:有日期、作者、標題,甚至和可以指定顯示出來回應的部分內容字數!
想直接安裝來用嗎?還是透過 JSON,不過可以快速安裝喔!你先登入你的 Blogger,然後點作者的安裝網頁,找 Recent comments widget,按下按鈕就安裝好了喔!
如果不喜歡他的順序和樣式,要自己改程式碼囉!

shiny 提到...

您好,用您的方法作最新回应,在firefox上正常显示,在IE上不行

Abin 提到...

To shiny:
目前我的 Blog 就是用文內提到的方法做的最新回應,我測試過三種瀏覽器 (Maxthon, Firefox, IE 6),看到都是正常的,我 Blog 的最新回應您的 IE 看得見嗎?
如果看得見,那可能是你在 hack 的過程有什麼錯誤喔..

shiny 提到...

你的回应都能看见,我的网页在IE显示时,有错误提示,说少了一个"}",可我就是把你的代码复制上去的啊。还有文章收合功能,初始打开时,总是同时看见“完整阅读”和“文章收合”2个button,只有在点击以后,才正常,弄不懂了。

谢谢

Abin 提到...

我剛剛又測試了一下,發現有一個狀況,如果在主頁同時加入「最新文章」和「最新回應」兩塊模組,在 IE 裡面的確會錯亂,原因是因為兩塊模組裡面有一些相同重疊的 Javascript 的函式在裡面。(Firefox 不會)
解決方法:把 Javascript 的宣告定義都移到範本的原始碼裡面,這樣只要範本裡面有一份,兩個模組都可以正常使用。
另外,我檢查過「最新回應」的原始碼實際再貼一次,範例裡面的 {} 是成對的,不會有少一個 "}" 的可能。我猜想可能是您在改文章收合功能的時候,不小心改漏了,所以導致收合功能不大正常。(因為我的文章收合功能,用到很多 Javascript,如果你在剪貼的時候稍稍錯了一個空白或是符號,很容易出錯)

猫米格格巫 提到...

谢谢大侠,文章收合我已经做好了。那个最新回应在新建的Blog上正常,把这个按照老blog风格编好的模板文件copy到老blog里后,还是不行,我估计是不是和我的帖子内容有关系.

sara 提到...

想请问一下大人

如何控制所显示的评论长度?

Abin 提到...

本文提到的方法並沒有辦法自訂回應的字數,如果你有這樣的需求,我上面也有提到其他的方法,請參考這篇原文。如果不會改,也可以點這裡直接按按鈕安裝。

wcshih 提到...

高人你好,請問若我的"最新文章"裡只想顯示標題,不顯示作者和日期,要將你的上述的範例程式碼做怎麼樣的修改呢?謝謝你!

wcshih 提到...

也就是說要照你說的把authorname和date的欄位拿掉的話,上述那段程式碼要改成怎麼樣才被接受?我直接刪掉+authorname+結果頁面變成一直loading...謝謝回答~

Abin 提到...

沒錯,應該是改這一行就行了:
temp += '<li><span class="item-title"><a href="'+link+'">'+ title +'</a> - '+authorname+' @ '+timestamp+'</span></li>';
變成
temp += '<li><span class="item-title"><a href="'+link+'">'+ title +'</a></span></li>';
這樣應該就只有標題和連結,沒有作者和日期,要小心一堆引號,多刪少刪都會出現你說的狀況。

禾本族 提到...

請問我可以限制秀在首頁上面的字數嗎~~因為我想限制秀出20字左右~~

豬尾巴 提到...

昨天晚上才搞好的「最新回應」,今天發現也有問題了,最後終於發現原來大家都一樣,至少在我局端來看,大家的「最新回應」都會有問題,顯示下載中卻沒有任何後續結果。

問題好像出在 ?max-results 變數,直至目前,我看到的狀況是火狐會跳出 "Too many instances of max-results" 的字串,IE直接回應無法顯示。試著把最大值改成5,仍然有問題。如果把變數拿掉卻可以顯示出預設的一二十個,莫名其妙。

To 禾本族
看你有用feedburner。我昨天研究它一個晚上,發現裡面有個功能 Publicize -> BuzzBoost,裡面可以限制字數。但是!如果要拿blogger的feed去餵feedburner,然後JSON在去抓feedburner,可能得修改程式碼。對我來說太麻煩,如果你功力好,可以試試看。(不過如果試成功不知能否通知小弟一下,感恩)

Abin 提到...

To 豬尾巴: 謝謝你的提醒,不然我這兩天比較忙,還真的沒發現原來最新回應不能用了。我去看原始網站,和 ?max-results 之類參數好像沒有關係,關鍵是在 Blogger RSS API 內部修正,而這個 Hack 用的 JSON 方式就失效了,所以是 Blogger 內部修改導致 Hack 失效。
現在好像有解法,不過我看起來是用 Yahoo Pipe! (RSS 處理的另一種管道),我很不喜歡,因此我也不打算採用,如果此問題無解,我只好搬出以前的舊方法來達到同樣的目的,到時候再改 Code 囉!

To 禾本族: 如果要限制字數,看看程式碼裡有一行:
var title=Comment.title.$t;
你可以改成
var title=Comment.title.$t.substr(0,你要的字數);
這樣就行了,不過現在 JSON 失效我沒辦法幫你確認,抱歉囉!
還有 豬尾巴 說的也是一種好方法,用 FeedBurner 去篩檢固定字數,如果成功也要和我講喔! : )

禾本族 提到...

TO 站長

限制字數我已經成功了喔~~謝謝啦~~
我還有個問題想請教
輪播的那個功能,是不是不能跟最新文章同時出現,因為我發現我版面上面如果只有最新文章與最新回覆是,是不會有問題,但如果加上文章輪播功能,這功能永遠都呈現LOADING字樣,但我只要拿掉最新文章,那我文章輪播功能就可以用了。

還有個問題想麻煩您
我要怎麼將輪播變成隨機~~

Abin 提到...

To 禾本族,你說的狀況我在文末的[注意]有提到喔,你如果同時用這個模組去做最新回應和輪播,也會有一樣的問題。(同時用兩個以上,變數和函示名稱一樣,Javascript 會錯亂)
改進辦法有兩種,第一種是更改模組名稱,像是範例裡用的叫 newComments, handleComments 這些字樣,你在不同模組(最新文章和輪播)用不同的函示和變數名稱以示分別就好。像是新文章都叫 newPost, handlePost,而輪播就都用 newBlog, handleBlog,以此類推..
第二種方法比較複雜,要把這個函示定義在樣版文件裡(而且要改寫函示),每個 Sidebar 模組要用的時候統一呼叫,這樣也可以解決這個問題。你看我Blog 的原始程式碼,是用第一種方法解決的。(同時用最新回應和最新文章兩個模組)

良夜 提到...

感謝你的教學,
我將這篇文章和「首頁長篇文章收合」二文的連結貼在我部落格文章中囉!

小飛 提到...

請問 我剛剛用了回又回應很成功

但是要如何把日期用掉 只要名字跟回應呢 還有字數好像不能改

我在我網誌剛剛裝你這篇回應那 案回應內容

不是跑道文章耶 而是跑出一個下載文件..這是正常嗎

謝謝大大 謝謝.. ??

Abin 提到...

To 小飛:
請參考回應 #18,不要日期就拿掉 timestamp 就好了。字數的部份請參考回應 #21,你的問題其他人都問過了。

Mr.ABay 提到...

您好,我在GOOGLE搜尋到很多,其中一個語法比較喜歡,可是不懂語言,自己亂改一直出錯,不知道能不能請教要怎麼改?

以下是我GOOGLE找到的:
http://chagg.blogspot.com/2007/07/blogger-pixnet.html

這個貼上之後,欄位會以--re:標題 這樣的形式出現最新回應的文章
可是我把.js的內容複製,直接貼上,這樣就亂掉了。

請問應該怎樣修正呢?

另外,如果想修改『出現回應的文章數量』,要修改哪邊的值呢?

謝謝~

Adley Chiang 提到...

您好,請問想要將 最新文章 直接顯示文章內容 那該怎麼修改?
麻煩教一下,謝謝你唷!

張貼留言

歡迎留言或發表意見,不過要理性不做人身攻擊。匿名的朋友得到回應的速度會比較慢喔~
發問相關的禮貌和規矩請先參考這篇文章,不當留言、和本文無關的回應可能會被直接刪除無視喔!