2014/08/14

Diazo Beginner Steps

累積 Diazo 的歷史和原理後,最近終於有個小案子能具體實戰。值得注意的是,套用 Diazo 時,並沒有存在特定的標準解法,需要搭配情境和資源現況,再決定從 Theme 或 Content 或 Rule 找到最容易下手的平衡點。

Theme 原始檔是從 ThemeForest 購買,樣版大致分成「首頁」「列表」「個別頁面」三大類,對初學者容易上手的步驟,是先修改首頁 HTML 符合自己的需要,再編寫 Rule 套用首頁的 Theme 和 Content,接著再逐步納入列表和個別頁面的樣版。編寫 Rule 的過程中,需要仔細比對 Content 和 Theme 的 HTML Tag 或是 XPath,為了方便比對,開啟兩個 browser 畫面,利用 Alt + Tab 切換。有個小撇步,在網址後面加上 ?diazo.off=1 就能暫時取消 Diazo 的效果,但在開發階段,全站式的取消效果會更方便。

以 http://diazo.mysite.com/ 為例,如果 Plone Site 在 http://168.168.168.168:8080/drchen 執行,可以在 http://168.168.168.168:8080/drchen/@@theming-controlpanel 指定 168.168.168.168 是「不套用佈景主題的網址」,這樣就可以在 http://diazo.mysite.com/ 顯示 Rule 生效後的結果,在 http://168.168.168.168:8080/drchen 顯示 Untheme Content 的結果。

網址的對應,是 Diazo Rule 最常見的設定工作之一。以下列 Theme 程式碼為例:

<a href="index.html">
<img src="img/logo.png" />
MySite Home</a>

它會被預設轉換成:

<a href="/++theme++drchen.theme/index.html">
<img src="/++theme++drchen.theme/img/logo.png" />
MySite Home</a>

對於圖檔而言,這樣的網址轉換並沒有造成困擾,但是 A Tag 就得額外處理。最直覺的方式,是讀取 Content 實際的 href 屬性值來取代,有趣的是,雖然是要「取代」 Link 值,但 Rule 語法要用 <copy /> 並指定 Attribute,用 XPath 選取 Node 的範例長得像這樣:

<copy attributes="href"
           theme="/html/body/div[2]/div[1]/div/div[1]/a"
         content="//*[@id='portal-logo']" />

我的理解是,想要取代 Node 時,才用 <replace />。接著,我們以 Global Section 為例,介紹幾個相關的對應情境。

想要逐一取代 Global Section 的 A Tag,我們可以仿照上述技巧,透過下列的範例語法來達成:

<replace theme="/html/body/div[2]/div[1]/div/ul/li[1]/a"
       content="//*[@id='portaltab-index_html']/a" />

不過,在這個例子裡,我們應該要連帶處理 <li class="selected"> 的部份,僅是取代 A Tag 的結果並未滿足實際的需要。那麼,取代整個 <ul /> 如何? 事實上,我們想留下 Theme 的 <ul> 但取代掉剩下的 <li /> 部份。幸好,有個 -children 語法能夠漂亮地處理這種需求:

<replace theme-children="/html/body/div[2]/div[1]/div/ul"
      content-children="//*[@id='portal-globalnav']" />

我有成功試過其他方法,是先修改 Global Section Viewlet 的 Template 內容,在 <ul> 加上 CSS Class 屬性值,再用 <replace /> 完成取代。相較之下,簡潔的 -children 語法就像一刀斃命。

有時候會遇到一個 Node 裡,同時有數個 A Tag 要指向相關的網址,參考下列的 Theme 原始碼:

<li>
<h2>
<a href="#" title="">
看診科別項目
</a>
</h2>
<div class="news clearfix">
<p class="text">
小兒科、過敏氣喘、耳鼻喉治療<br>
內科、慢性病處方簽<br>
成人、小兒感冒 等
</p>
<a href="#" title="">更多說明</a>
</div>
</li>

利用 //a 的 XPath 語法,可以指定 Node 裡的所有 A Tag,參考下列的 Rule 範例:

<copy attributes="href"
         theme="/html/body/div[2]/div[2]/ul/li[1]//a"
       content="//*[@id='portletwrapper-ID']/dl/dt/span[2]/a" />

1 comment:

marr said...

When trying with http://docs.diazo.org/ you might want to check https://github.com/plone/diazo/blob/master/docs/quickstart.rst first for possible updates. Note that it's easy to run into "AssertionError: Hop-by-hop headers not allowed". Besides, I create a HTML file in Nginx document root folder to try using it as "address = http://mysite.com/diazotest.html" but it seems to return the content of http://mysite.com/ instead.