2008-09-25

Blogger 打造紀實 - 功能強化 (Alterations for Enhancement)

Blogger Logo這篇記錄的是,只要稍加修改 Blogger 版面配置的 HTML,或是加上簡單的 JavaScript 抑或是 Blogger 的語法及 CSS 的搭配,就可以輕鬆達到的 Blogger 功能強化。關於 Blogger 的語法,其實在 Blogger 的說明【Blogger Help > Customize Your Blog > Layouts > Advanced Use】中,關於頁面的構成,邏輯的語法,參數項目及內容等等,就都有挺完整的介紹,有興趣可以參考看看。當然,對 HTML、CSS、JavaScript 這些基本語法的熟悉程度,多多少少有點幫助,至少可以降低因陌生與不熟悉所產生的修改時的恐懼感。

功能列表:


繼續閱讀 (ReadMore) 功能:這算是個『國民功能』吧!(笑)
基於訂閱者各閱讀器的相容性及用戶端執行效能考量,而採用了 Blogger 語法 搭配 HTML 與 CSS 的做法來達成這個功能。這作法也是 Blogger 官方說明文件【如何建立可擴充的文章摘要?】裡所寫到的。

首先,在 HEAD 的區間內,加入以下的 Blogger 語法 + CSS 的區段:

/* ### 20080616 CSS for the function Read More ### */
/* 當 pageType 是『內文』的時候,呈現完整內容,否則則隱藏 */
<b:if cond='data:blog.pageType == "item"'>
span.fullpost {display:inline;}
<b:else/>
span.fullpost {display:none;}
</b:if>
接下來就是文章主體的部份(<data:post.body/>),同樣的也是運用 Blogger 語法來判斷現在的 pageType 是不是在內文中,藉以決定該顯示的項目。Blogger 語法 + HTML 的區段:

<!-- ### 20080616 Logic modified for the function Read More ### -->
<!-- 當 pageType 是『內文』的時候,呈現完整內容,否則則隱藏。 -->
<b:if cond='data:blog.pageType == "item"'>
<!-- 文章內文 -->
<data:post.body/>
<!-- 當其它 pageType 的時候,只要顯示引文摘要 -->
<b:else/>
<!-- 文章內文 -->
<data:post.body/>
<!-- 繼續閱讀連結 -->
<br/><br/><a class='readmore' expr:href='data:post.url' expr:title='data:post.title'>繼續閱讀…</a>
</b:if>
先別太興奮,以上只是前戲準備工作,並不是弄好這樣就好了,在張貼文章的時候,也要有配合些許的改變,才能讓這樣的設計發揮作用:文章在撰寫的時候,除了引言摘要的部份,其它就以 <span class="fullpost">其它內容</span> 來包覆。

提供一下我在『設定 > 格式 > 文章範本』裡的設定,就可以一目瞭然:

引言摘要
<span class="fullpost">
其它內容

</span>
說穿了,這樣的實作,想法跟原理都很簡單,藉著先前所加入的 CSS 語法的設定,將使得 fullpost 所包覆的部份在不是瀏覽內文的情況下被隱藏,而達成『繼續閱讀』的功能目標。

2010-05-23 UPDATED: Blogger 官方簡潔版繼續閱讀釋出
其實是有點後知後覺了,在 Blogger 官方說明文件【建立「繼續閱讀」摘要】有釋出了這樣一個簡潔的作法,不需要異動任何令人眼花撩亂心生恐懼的版型定義 HTML 程式碼,就可以輕易地透過文章編輯器為網誌文章建立「繼續閱讀」。

但是要使用文章中所示範的新版的文章編輯器,可能需要參考一下這篇 Blogger 官方說明文件【新版文章編輯器總覽】有詳細的介紹如何開啟及新版功能。(此功能尚未正式釋出,所以要在 Blogger 測試區的後台介面中開啟。)

說穿了,按下文章編輯器的「Jump Break」按鈕後,它的動作就是在原始檔中插入了:
<!--more-->在了解這一點後,如果覺得新版的文章編輯器不合用,或是對它編輯出來的 HTML 原始碼有疑慮,大可以自行手動加入,十分方便快速,效果也相同。

然而,在此介紹的兩種「繼續閱讀」功能,彼此並不相衝突,且可以並存。如果要做的文章摘要比較複雜時,比方說要某一段的某段文字加上其他段落的某段文字,就可以用上面較複雜的版本。如果只是很單純的摘要,那簡潔版的作法是不錯的選擇。

遺憾的是,不論是哪一種,都只影響文章列表頁面的版面,對 RSS Feed 的輸出是兩碼子事,如果需要的是控制 RSS Feed 的輸出內容,可以參考這篇【Blogger 打造紀實 - 自定訂閱 (Build Your Own RSS Feed)】。



相關文章/延伸閱讀 (RelatedPosts) 功能:
這算是一種行銷的手法吧!告訴你的訪客,還有哪幾篇是類似或跟這篇文章相關的,可以讓訪客很自然的被引導瀏覽,就像 Google 的廣告會依據瀏覽頁面的內容來判斷要秀相關聯的廣告,而大大提高點選機率的作法一樣,一方面也算是方便訪客讓他們能更方便的找到相關主題的文章。說來容易,做起來其實卻挺麻煩。最傳統的作法,可能就是自己一個一個的去把連結拉進來放,但是這樣可一點也不 Smart!在網路上,搜尋到了一些做法,就依樣畫葫蘆嚕!
參考連結:

首先,在 HEAD 的區間內,加入以下的 CSS 與 JavaScript Functions:

<style type='text/css'>
/* ### 20080616 CSS for the function Related Posts ### */
.relatedPost {text-align: left;}
.relatedPost .caption {
margin:-10px;
line-height:1.5em;
background:url("大綠箭頭的圖形網路位址") no-repeat 10px .5em;
padding:2px 14px 2px 29px;
}
.relatedPost ul {
list-style:none;
margin:0 0 1.25em;
padding:15px;
}

.relatedPost ul li {
background:url("小綠箭頭的圖形網路位址") no-repeat 2px .25em;
margin:0;
padding:0 0 3px 16px;
margin-bottom:3px;
border-bottom:1px dotted #AAAAAA;
line-height:1.4em;
}
</style>
<!-- ### 20080616 Variables & Functions for the Related Posts. ### -->
<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) {
if(typeof(json.feed.entry)!="object") return;// ###
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('延伸閱讀:
    ');
    while (i < relatedTitles.length && i < 5) {
    document.write('
  • ' + relatedTitles[r] + ' - ' + relatedDates[r] + '
  • ');
    if (r < relatedTitles.length - 1)
    r++;
    else
    r = 0;
    i++;
    }
    document.write('
');
}
}
//]]>
</script>
這邊我改了幾個地方:
  1. 對應的 CSS 定義是原來沒有的…我挖頁面裡其他部分拼拼湊湊定義出來的…
  2. 雖然本來就有強調標籤中不能含有保留字元,但是我不想因為這個功能缺陷而放棄標籤中的特殊字元…(PL/SQL啊~你那條線沒事幹嘛斜右上左下啊啊啊啊~),原來的程式會跳錯,試了幾個 URL Encoding 的作法都無解。目前作法的配套措施是直接把出錯的程式點強制跳掉,然後文章伴隨別的正常標籤,像 PL/SQL 就跟 Oracle 成對出現,這樣雖然 PL/SQL 標籤導致功能錯誤被跳掉了,還有 Oracle 標籤可以補撈相關文章資料。

再來,就是在呈現標籤的迴圈裡卡進收資料的動作了。

<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>
<!-- ### 20080618 Related Posts : collect the labels via rss in the json format. ### -->
<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>
</b:loop>
</b:if>
然後,挑塊風水寶地放置,就好嚕!不過一定要確認在上面收資料的動作已經完成之後的地方就是了…

<b:if cond='data:blog.pageType == "item"'>
<!-- ### 20080618 Related Posts : Print the title for the posts. ### -->
<!-- ### 20080619 modify the layout for the related posts. ### -->
<div class='relatedPost'>
<script type='text/javascript'>
ShowRelatedPosts('<data:post.url/>');
</script>
</div>
</b:if>
白話來說,這種作法就是取得該文章的標籤後,然後依照這些標籤,然後去取擁有同樣標籤的文章資料回來,條列秀出。嗯!Smart!但是,萬一標籤很多,效能的低落恐怕就是要付出的代價了。不過,套個資料庫的觀念來說明,如果每個欄位都是 Index (索引)的話,那 Index 也就失去它的意義了!同樣的,如果,文章歸屬太多的分類,那可能分類的方式就得檢討一下了。



圖片燈箱 (LightBox) 效果 (20080924 Extended; 20090511 Updated):
燈箱(LightBox)效果這是啥!?點下面這張圖就能明白啦!
LightBox Demo
酷齁!官網在這 LightBox 2

LightBox 2 官網把檔案下載下來之後,打開壓縮檔,以下幾個檔案是必備的:
  1. jscss 目錄下的所有檔案。
  2. images 目錄下的 loading.gif、closelabel.gif、prevlabel.gif 與 nextlabel.gif
得在網路上找個地方擺放這幾個檔案以供引入與使用。

然後有幾個地方需修改:
  1. 修改 lightbox.js 中的圖形檔案位置:
    把 images/loading.gif 與 images/closelabel.gif 修改成放置圖形的 URL 位址。
    //
    // Configurationl
    //
    LightboxOptions = Object.extend({
    fileLoadingImage: 'images/loading.gif',
    fileBottomNavCloseImage: 'images/closelabel.gif',
    // 把它們修改成這樣
    fileLoadingImage: 'http://檔案位置URL/loading.gif',
    fileBottomNavCloseImage: 'http://檔案位置URL/closelabel.gif',
    ...

    }
  2. 修改 lightbox.css 中的圖形檔案位置:
    ../images/prevlabel.gif../images/nextlabel.gif 修改成放置圖形的 URL 位址。
    #prevLink:hover, #prevLink:visited:hover { background: url(../images/prevlabel.gif) left 15% no-repeat; }
    #nextLink:hover, #nextLink:visited:hover { background: url(../images/nextlabel.gif) right 15% no-repeat; }
    /* 修改成這樣 */
    #prevLink:hover, #prevLink:visited:hover { background: url(http://檔案位置URL/prevlabel.gif) left 15% no-repeat; }
    #nextLink:hover, #nextLink:visited:hover { background: url(http://檔案位置URL/nextlabel.gif) right 15% no-repeat; }
  3. 在 Blogger 後台「版面配置 > 修改 HTML」裡進行引入:
    在 head 區段裡,加入 相關 js 檔案及 css 檔案的引入。
    <head>
    <link type="text/css" rel="stylesheet" href="http://檔案位置URL/lightbox.css" media="screen" />
    <script type="text/javascript" src="http://檔案位置URL/prototype.js"></script>
    <script type="text/javascript" src="http://檔案位置URL/scriptaculous.js?load=effects,builder"></script>
    <script type="text/javascript" src="http://檔案位置URL/lightbox.js"></script>
    </head>

其實,一開始看到引入的檔案裡有 prototype,我眉頭就皺了一下。不是說 prototype 不好,不可否認,它仍然是 JavaScript FrameWork 裡的翹楚之一(而且老實講,JavaScript FrameWork 我心另有所屬…改天有機會再另行介紹),但是,有必要為了一個效果,去引入整個的 JavaScript FrameWork 嗎!?像這種阿肥,可以用一些壓縮程式先幫它減肥一下,沒辦法,龜毛為進步之本!還好,prototype 用 Base62 Encode 壓縮過之後的檔案大小還在可接受的範圍。
線上 JavaScript 壓縮工具:

然後,像這種引入很多個檔案的,我心中就會有疙瘩,就像棒球賽裡多一次傳球就多一次失誤的機會的道理一樣。稍微看過 scriptaculous.js 之後,發現它的工作就只是單純負責載入另外兩個 Scripts,所以,我就把 effects.js,builder.js,lightbox.js 三個檔案,擬照瀏覽器的行為模式依序合併成一個檔案,講的很玄,其實不過就是無腦的 copy & paste 而已。然而,這個整合過的 Script 很不幸的,並不能用壓縮工具來自動演算與壓縮,我試過很多種選項組合與方式都會跳錯,當然,如果有人願意分享心得並指點一二,自然是感激不盡。一來我真的懶得太去細看裡頭交互的動作,二來個人龜毛之極致,最後我還是採用人工壓縮的方式把它們合併了。做完這個動作,scriptaculous.js 的引入就可以被整個省略掉了。

經過這些壓縮與整併,LightBox 2 的安裝,相對付出的代價就並不是太大了,所以就正式把 LightBox 這功能給放進來了。引入的語法也變成這樣:
<head>
<link type="text/css" rel="stylesheet" href="http://檔案位置URL/lightbox.css" media="screen" />
<script type="text/javascript" src="http://檔案位置URL/prototype.js"></script>
<script type="text/javascript" src="http://檔案位置URL/lightbox2.js"></script>
</head>
我還在盤算著,說不定因為導入了 prototype JavaScript Framework,往後也更名正言順的可以導入更多的應用…那就再說了…

20090511 UPDATED: 修正 LightBox2 在 IE 造成「無法顯示網頁」的問題:
因為發現部分的時候,LightBox2 在 IE 造成「無法顯示網頁」的問題,導致一進網站就會整個當掉,偏偏 IE 的使用人口眾多,為了一個效果導致大部分的訪客無法瀏覽難免有因小失大考量,所以這效果擺放了不到一週,阿布就將它移除了。而後來發現應該是載入不全而執行的時候,就會誘發這種狀況,這也得歸咎於 IE 的 JavaScript 載入與執行的行為上與眾不同所以有體質特別衰弱的現象。

解決的方法是,把實際執行 JavaScript 程式行為的時間點往後拉,確保該有的物件都被載入完成後再進行執行的行為,就可以避免發生 IE「無法顯示網頁」的問題。程式碼放置位置修改如下:
<head>
<link type="text/css" rel="stylesheet" href="http://檔案位置URL/lightbox.css" media="screen" />
<script type="text/javascript" src="http://檔案位置URL/prototype.js"></script>
</head>
<body>
其他網頁物件
<script type="text/javascript" src="http://檔案位置URL/lightbox2.js"></script>
</body>
有點畸形的位置,不過,為了解決問題也只好睜一眼閉一眼了。


  • 20080702 建立發佈
  • 20080925 更新發佈
  • 20090511 修正 LightBox2 在 IE 造成「無法顯示網頁」的問題
  • 20100523 Blogger 官方簡潔版繼續閱讀釋出

4 回應 :

我有些问题不会。你有messenger吗?你方便add我吗?jessie87_ng@hotmail.com

你的跟我的差好多喔...我的真是太貧乏了..可是你的好深澳喔..我也可以在線上問你嗎?

請教您一個問題,我想在blogger的文章中,放入一個區塊,在區塊中顯示blogger中某一個標籤的最新文章標題和摘要,可以做得到嗎?

大大功力高強,也是想跟你請教一些在IE中無法正確顯示LIGHTBOX的問題,方便可否在MSN中跟你請教,感恩!
mt.mt0066@msa.hinet.net

張貼留言

讓阿布知道你對這篇文章的想法吧!