在前篇文章裡,我們已經建置了 Event Folder 和 Signup 兩個型別,接著,仍要依照專案需求,繼續調整功能及程式邏輯。展現網站功能的時候,我們總希望它能緊密結合視覺設計成果,另一方面,套用新的視覺設計時,會希望它不影響既有的程式邏輯。那麼 Plone 如何做到這個要求?控制視覺設計的檔案又放在哪裡呢?
Plone 系統預設的網頁呈現效果,著重在功能上,而且緊扣著內容管理的動線邏輯,這在 Intranet 的場合,可能已經足夠,但在對外服務的網站場合,通常需要調整頁面。在本文裡,我們將介紹佈景主題、視覺元件、動態網頁的相關技巧。
之前介紹過 buildout.cfg 檔案,裡面有個 debug-mode 參數,記得要指定為 on,執行 bin/buildout 生效後,它會動態記錄在 parts/instance/etc/zope.conf 裡面,線上的 Plone 就會即時反應 HTML 和 CSS 的修改結果,在 ZMI 的 portal_css 或 portal_javascripts 裡,也看得到 Development mode 選項啟用中,如圖1 所示。
▲ 圖1 portal_css 的 Development mode 選項
瀏覽器通常會搭載輔助工具,協助存取 HTML、CSS、JavaScript 檔案資源,以 Firefox 為例,搭配安裝 Firebug 後,利用 inspect 選項檢視 layout 和網頁元件,或是離線編輯 HTML 和 CSS 內容,都能帶來事半功倍之效,如圖2 所示。
▲ 圖2 Firebug 操作畫面範例
以上只是最基本的選項及工具,想要調整更多項目,當然可以搭配其他工具,或是自行閱讀工具的細項說明。
我們把 Theme 稱為「佈景主題」,它是網站整體視覺設計的成果,包括 layout、color、icon 之類的設計元素,還有 page template、style sheet、image、javascript 資源檔案。
Plone 4.0.x 預設的佈景主題稱為 Sunburst,值得一提的是,部份功能使用 AJAX 效果,畫面外觀如圖3 所示。
▲ 圖3 Sunburst 佈景主題畫面
Sunburst 的 layout 概分為四個區塊,如圖4 所示。
1. 表頭區塊
2. 主要內容區塊
3. 資訊方框區塊
4. 表尾區塊
▲ 圖4 Sunburst 的 layout 示意
就既有的系統架構而言,佈景主題是 Plone 裡的一個模組,想換佈景主題,跟啟用新模組的步驟一樣,先在 buildout.cfg 加上模組名稱,下載安裝後,再到 Plone Setup 的 Theme settings 裡選定想要的佈景主題,如圖5 所示。
▲ 圖5 佈景主題設定畫面
在 Default theme 下拉選單裡,可以看到 Plone Classic Theme 選項,它是 Plone 4.0.x 以前的預設佈景主題。
由於佈景主題模組裡的許多元件,也都適合獨立介紹和運作,因此,我們另外將它們統稱為視覺元件。目前 Plone 處理視覺元件的架構,整理如圖6 所示。
▲ 圖6 Plone 視覺元件架構
實作視覺元件時,具體的方式主要分成四類:
1.Skin Layer 方式-通常是透過 ZMI 的 portal_skins 目錄,編輯裡面的 Page Template、CSS、Python Script。這個機制屬於舊的方式,它的功能可以完整由下列的其他方式取代。
2.Browser View 方式-View 由 Python class 和 Page Template 組成,透過 configure.zcml 檔案註冊後,可以透過 https://localhost/mysite/@@my_view 的形式來執行。
3.Viewlet 方式-和 Browser View 類似,但需要搭配一個 Viewlet Manager 來註冊。
4.Portlet 方式-和 Viewlet 類似,但可以搭配設定檔,在特定的 Portlet Manager 裡顯示。它的顯示位置預設在 layout 的資訊方框區塊裡。
這麼多種方式,不如找一個簡單的切入點來示範,例如我們只想調整佈景主題裡的一部份,像是取消搜尋方框的顯示,該怎樣辦呢?
以 Plone 網站首頁為例,諸如 logo、搜尋方框、導覽列,都是一個 Viewlet,數個 Viewlet 再由一個 Viewlet Manager 管理。管理者可以從 https://localhost:8080/mysite/@@manage-viewlets 之類的網址,進入 Viewlet 管理介面,如圖7 所示。
▲ 圖7 @@manage-viewlets 管理介面
每個 Viewlet 都有自己的名稱,像 logo 的名稱是 plone.logo,每個 Viewlet Manager 也有自己的名稱,像表頭區塊的名稱是 plone.portaltop。同時,Viewlet 可以被指定隱藏或顯示,以 plone.searchbox 為例,點擊 Hide 選項後,搜尋方框就被取消顯示,另外,也可以在同一個 Viewlet Manager 裡調整順序,如圖8 所示。
▲ 圖8 Viewlet 設定項目示範
透過 Viewlet 和 Viewlet Manager,可以輕鬆管理 Portlet 之外的視覺元件大項,但是,Viewlet Manager 的順序和顯示與否,又是如何被控制的呢?
在 ZMI 的 portal_skins 裡,點選 Properties 頁籤,在畫面下方可以看到 Default skin 設定為 Sunburst Theme,因此 Sunburst Theme 的 Skin Layer 清單項目,包括 custom、sunburst_images、sunburst_templates,會依序被讀取,如圖9 所示。
▲ 圖9 Sunburst Theme 的 Skin Layer 清單
回到 portal_skins 的 Contents 頁籤,從 sunburst_templates 可以找到一個 Filesystem Directory View 物件,名稱叫做 main_template,它就是控制 Viewlet manager 順序和顯示與否的檔案,如圖10 所示。
▲ 圖10 sunburst_templates 包含的 main_template
sunburst_templates 是一個 Skin Layer 目錄,main_template 是一個 Page Template 檔案,留意到程式碼的內容呈現灰色底,代表不能修改,要點選 Customize 按鈕後,才可以修改 main_template 的程式碼,如圖11 所示。
▲ 圖11 點選 Customize 按鈕可以修改 Page Template
上述動作會把 main_template 檔案,從 sunburst_templates 複製到 custom 目錄,留意到程式碼的內容呈現白色底,代表可以編輯,試著讓<div tal:replace="structure provider:plone.portaltop" />失效,這代表取消 plone.portaltop 這個 Viewlet Manager 的顯示,如圖12 所示。
▲ 圖12 編輯 main_template 取消 plone.portaltop
練習操作後,讓我們檢視 Skin Layer 的運作原理。以 Sunburst Theme 為例,Plone 會由上而下尋找資源檔案,也就是 custom、sunburst_images、sunburst_templates 之類的順序,尋找資源檔案,如圖13 所示。
▲ 圖13 Sunburst Theme 的 layer 順序設定值
每個 layer 裡包含數個資源檔案,像是圖檔、CSS、Page Template 檔案,例如 sunburst_images 裡找得到許多圖檔,sunburst_styles 裡找得到許多 CSS 檔案。
數個 layer 可以組成一個 Theme Skin,以 Plone Default 為例,這個 Skin 最上層的 layer 是 custom,如果 custom 目錄裡有個 logo.jpg 圖檔,它會蓋掉 plone_image 目錄裡的 logo.jpg,如圖14 所示。
▲ 圖14 custom 目錄的資源檔案優先被讀取
圖檔 logo.jpg 的來源,可以進入某個 layer 點擊 Custom 按鈕獲得,也可以直接在 custom 目錄,從項目下拉選單新增 Image 獲得。我們沒有示範 CSS 或其他資源檔案的例子,但它們的運作原理跟操作方式,都是完全一樣的。
Skin Layer 雖然是舊的方式,由於設定方式簡單,目前還是常被使用,像是換 logo 套 CSS 的場合,特別適合用這種方式。
如前所述,不管用哪一種視覺元件的處理方式,都會牽涉 Page Template,接著,我們把焦點放在這個資源檔案上。
Page Template 有時也稱為 Zope Page Template (ZPT),在檔案系統裡,它的副檔名是 .pt,以 XHTML 為基礎,也就是相容於 XML 標準的 HTML 語法,XHTML 要求程式碼符合 well formed 格式,例如使用 <img />、<span></span>這樣的格式,還有正確的巢狀結構,並使用小寫英文的標籤格式。
Page Template 使用 Template Attribute Language 動態網頁語法,簡稱為 TAL。在 TAL 裡,包含了描述屬性資訊的標籤語法,最簡化的 TAL 語法範例,參考圖15 所示。
▲ 圖15 TAL 標籤語法示意
其中 <title>... </title>是原本 HTML 語法的部份,tal:content="here/title" 的部份則是 XML namespace,TAL 語法統一以 tal: 為首,content= 部份用來指明要設定 的內容,而 "here/title" 是 TAL 的 expression 內容,這類的 expression 被規定在 TAL Expression Syntax (TALES) 裡。
當網頁版面人員使用 Dreamweaver 之類的工具,讀取上述 XHTML 原始碼時,並不會造成無法解讀的困擾,畫面上會順利出現「Page Title」的標題字樣。當這樣的 Page Template 檔案存放於 Zope 系統裡,它會搭配物件的屬性值與物件方法,動態產生網頁內容,包括執行邏輯判斷和錯誤處理等。
不過,Page Template 不應該拿來處理 subroutine 或 class,這類的程式功能,應該寫在 Python Script 裡,再由 Page Template 呼叫取值和顯示。接著,為了入門練習的用途,我們直接在 ZMI 裡,搭配 Plone 系統來建立最簡單的 Page Template。
為了練習用途,我們先在 ZMI 的 Plone Site 裡,從新增物件項目的下拉選單,選擇 Page Template,如圖16 所示。
▲ 圖16 在 ZMI 裡新增 Page Template
在新增頁面的 Id 欄位填寫識別碼,以 mypage 為例,它會成為 URL 的一部份,點選 Add and Edit 按鈕,如圖17 所示。
▲ 圖17 Page Template 新增頁面
在編輯頁面,可以看到預設的程式碼內容,點選 Save Changes 將程式碼儲存生效後,就可以點選 Test 頁籤,檢視程式碼的執行結果,如圖18 所示。
▲ 圖18 Page Template 編輯頁面
預設的執行結果,只出現的簡單畫面,包括 title 和 id 這兩個動態產生的變數值。回到瀏覽器的前一頁後,可以繼續編輯 Page Template 的程式碼內容,如圖19 所示。
▲ 圖19 預設的 Page Template 執行畫面
試著在圖4 的 Title 欄位,填上內容,按 Save Changes 後,再次測試時,會看見剛才填上的 Title 內容。
那麼,我們該如何套上佈景主題,或是讓網頁看起來更豐富呢?
套用佈景主題的方法,是在<html>裡使用 metal:use-macro="context/main_template/macros/master",並在<body>裡使用<metal></metal>標籤語法,簡化的程式碼範例,如圖20 所示。
▲ 圖20 使用 METAL 語法的 Page Template
我們利用 METAL (Macro Expansion for TAL) 語法,快速引用原本的佈景主題設計成果。上述程式碼範例的顯示結果,如圖21 所示。
▲ 圖21 套用佈景主題的 Page Template 執行結果
巨集 (Macro) 的功能,是讓特定的 HTML 段落,能夠重覆被使用。METAL 是搭配 TAL 的巨集語法,語法以 metal: 開頭,先要有個 define-macro 的內容,後來的 Page Template 才可以用 use-macro 引入巨集內容。例子裡的 use-macro="context/main_template/macros/master",表示在 main_template 裡有定義一個名稱為 master 的巨集,如圖22 所示。
▲ 圖22 main_template 定義的 master 巨集
利用 TAL 和 METAL,Page Template 可以把 Viewlet 和 Viewlet Manager 串連起來,利用 Skin Layer,則可以在 ZODB 裡存取檔案系統裡的資源檔案,這些工具和方法,是建立 Plone 視覺元件的入門基礎。即使我們還未介紹 Browser View 的細節,也能完成不少佈景主題的調整,透過 ZMI 就能搞定,未必要在檔案系統裡進行。
關於佈景主題和視覺元件,仍有許多技巧值得介紹,像是結合 AJAX 功能,在檔案系統裡註冊資源檔案的方法,我們將在後續的篇幅裡示範。對於 TAL 感到意猶未盡的朋友,可以上網尋找更多範例。最後,值得一提的是,TAL 並不是 Zope 獨有的語法工具,PHP 環境也可以使用它,例如 PHPTAL,這是跨語言技術擴散的另一例。