原文出處 http://abintech.azhai.org/2007/03/related-post.html
轉貼教學
Blog 文章一多,分類標籤的運用在找尋特定文章時就很重要。當有些讀者從外面的搜尋引擎或 RSS 連進來看 Blog 特定文章的時候,在文章的後面隨機列出一些相關文章的標題,一方面可以讓讀者找到更多對方可能會感興趣的 Post,另一方面也可以吸引讀者多去瀏覽自己其他的文章。Blogger 系統所有的文章都有靜態連結網址,看起來頁面內容並不是「動態」從資料庫抓出來的(除了那些要去即時收集的模組),所以在單篇文章的後面亂數挑出一些相關的文章表列出來,應該也不會太花時間。
原理其實很簡單,透過文章分類標籤的 RSS Feed,找出一些和該篇文章有相同標籤的文章,它們就是「相關文章」,然後亂數挑出幾篇,過濾內容將標題、連結和日期列出就大功告成了。在網路上找到了一些範例,其實不大滿意,因為有個 bug:相關文章應該是排除本文之外有相同分類標籤的文章,偏偏這些範例挑亂數的時候有可能會挑到本文,這樣就會看到相關文章模組內還有本文標題在裡面的奇怪情況(邏輯上是沒錯啦)。所以看到這些範例除了例行性會去修改增加可讀性外,還要自己去解決這個 Bug。這個 Hack 應該是我 Blog 最後一個大規模的修改,之後除了調整 CSS 和外觀外,差不多想弄得功能都弄完了~
老樣子,要修改之前要先備份樣版。首先,塞入以下這段 Javascript (在 </head> 標籤前):
<script type='text/javascript'> //<![CDATA[ <!-- Script functions for Related Posts: RelatedLabels(), RemoveDuplicatedPosts(), contains(), ShowRelatedPosts()--> var relatedPostsNum = 0; var relatedTitles = new Array(); var relatedUrls = new Array(); var relatedDates = new Array(); function RelatedLabels(json) { for (var i = 0; i < json.feed.entry.length; i++) { var entry = json.feed.entry[i]; relatedTitles[relatedPostsNum] = entry.title.$t; relatedDates[relatedPostsNum] = entry.published.$t.substr(0,10); for (var j = 0; j < entry.link.length; j++) { if (entry.link[j].rel == 'alternate') { relatedUrls[relatedPostsNum] = entry.link[j].href; relatedPostsNum++; break; } } } } function RemoveDuplicatedPosts(PostUrl) { var tmpUrls = new Array(0); var tmpTitles = new Array(0); var tmpDates = new Array(0); function contains(a, e) { for(var j = 0; j < a.length; j++) if (a[j]==e) return true; return false; } for(var i = 0; i < relatedUrls.length; i++) { if(!contains(tmpUrls, relatedUrls[i]) && PostUrl != relatedUrls[i]) { tmpUrls.length += 1; tmpUrls[tmpUrls.length - 1] = relatedUrls[i]; tmpTitles.length += 1; tmpTitles[tmpTitles.length - 1] = relatedTitles[i]; tmpDates.length += 1; tmpDates[tmpDates.length - 1] = relatedDates[i]; } } relatedTitles = tmpTitles; relatedUrls = tmpUrls; relatedDates = tmpDates; } function ShowRelatedPosts(PostUrl) { RemoveDuplicatedPosts(PostUrl); var r = Math.floor((relatedTitles.length - 1) * Math.random()); var i = 0; if (relatedTitles.length > 0) { document.write('Related Posts: <ul>'); while (i < relatedTitles.length && i < 5) { document.write('<li><a href="' + relatedUrls[r] + '">' + relatedTitles[r] + '</a> - ' + relatedDates[r] + '</li>'); if (r < relatedTitles.length - 1) r++; else r = 0; i++; } document.write('</ul>'); } } //]]> </script> |
獨獲創見的部分就是把該篇本文的 URL 當變數傳入 Javascript Function 裡,在剔除重複文章的時候把自己一併從陣列裡刪掉,這樣就解掉上述的 Bug 啦!此外,程式裡紅字的部分,是用來控制相關文章的數量,我預設用五篇,請依個人需要修改。接下來,就是塞入收集相關文章的 Javascript,找到下面這段在文章內容後面顯示分類標籤的程式:
<b:if cond='data:post.labels'> <data:postLabelsLabel/> <b:loop values='data:post.labels' var='label'> <a expr:href='data:label.url' rel='tag'><data:label.name/></a><b:if cond='data:label.isLast != "true"'>,</b:if> </b:loop> </b:if> |
在迴圈結束 </b:loop> 前面加入呼叫收集相關文章的code:
<!-- Fixed for Related Posts --> <b:if cond='data:blog.pageType == "item"'> <script expr:src='"/feeds/posts/default/-/" + data:label.name + "?alt=json-in-script&callback=RelatedLabels&max-results=10"' type='text/javascript'/> </b:if> |
同樣的,紅色的部分也是用來限制數量,每個標籤抓出最近的幾篇文章來匯總(該數字至少要 >= 上面 Javascript 裡定義顯示的數量。數字加大,可以增加相關文章的亂數樣本,也就是相關文章可以顯示越多舊的相關文章)。抓完文章當然就是找地方顯示囉!只有一個限制:一定放要在文章分類標籤那段的後面(就是一定要呼叫過上面那段,這樣也才會有相關文章可以顯示啊~),所以我就直接放在後面(上面這段 </b:if> 標籤的後面就可以,位置依自己的樣版外觀調整),這部分呼叫顯示相關文章的程式碼如下:
<!-- Fixed for Related Posts --> <b:if cond='data:blog.pageType == "item"'> <script type='text/javascript'> ShowRelatedPosts('<data:post.url/>'); </script> </b:if> |