Diazo By Example
Tips
常用的技巧,是利用 @@manage-viewlets 管理介面,把不需要的動態內容取消顯示,再利用 z3c.jbot 調整 Page Template 內容,像是 global_section 的 title 內容。
Simplest Rule
<?xml version="1.0" encoding="UTF-8"?> <rules xmlns="http://namespaces.plone.org/diazo" xmlns:css="http://namespaces.plone.org/diazo/css" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <rules css:if-content="#visual-portal-wrapper"> <theme href="homepage.html" /> </rules> </rules>
其中的 css:if-content 讀成「如果 Content 裡出現符合的 CSS 屬性值」,也就是「#visual-portal-wrapper」的話,就使用 homepage.html 檔案作為 Theme 內容。
以上範例的結果,只回傳 Theme 的原始內容,原則上沒有更改。精確地說,它至少會把 Theme 的相對路徑,像是:
<link rel="stylesheet" href="css/style.css" type="text/css" />
改成絕對路徑,假設 my.theme 是擴充模組的名稱:
<link rel="stylesheet" href="/++theme++my.theme/css/style.css" type="text/css" />
接著,最簡單的更改,是套用 Content 的 <title /> 值:
<?xml version="1.0" encoding="UTF-8"?> <rules xmlns="http://namespaces.plone.org/diazo" xmlns:css="http://namespaces.plone.org/diazo/css" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <rules css:if-content="#visual-portal-wrapper"> <theme href="homepage.html" /> <replace css:theme="html head title" css:content="html head title" /> </rules> </rules>
其中的 <replace> / 是一種 Rule Directive,它會讀取 Content 內容值,取代 Theme 的對應位置。上述範例就是把 Content 的 <title /> 內容,取代 Theme 的 <title /> 位置,也就是改成:
<title>Welcome to Plone — My Site</title>
如果是 <replace css:theme="html body h1" css:content="html head title" /> 就會把 Content 的 <title /> 填進 <h1 /> 位置,如果 Theme 有兩個 <h1 />,則兩個都會被改成 <title /> 的內容。這個範例在實務上並無意義,它只是用來示範 Rule Directive 的功能。
上述的 <css:theme=”html head title”> 和 <theme=”/html/head/title”> 同義,因此整個 Rule 程式碼可以用 <replace theme=”/html/head/title” content=”/html/head/title” /> 來取代。
類似的範例是:
<replace theme="/html/head/link[@rel='shortcut icon']" content="/html/head/link[@rel='shortcut icon']" />
它使用 Content 的 favicon 來取代 Theme 的 favicon 網址。
Common Tasks
Replace Theme Title with Content Title
<replace css:theme="html head title" css:content="html head title" />
Drop FavIcon from Content; Use the One from Theme
<drop content="/html/head/link[@rel='shortcut icon']" />
Copy Base Tag from Content
<before css:theme-children="html head" css:content="html head base" />
Copy Meta Tags from Content
<after css:theme-children="html head" content="html/head/meta" />
What happens if replace
is used?
<replace css:theme="head meta" css:content="head meta" />
In case there are 2 <meta> in theme and 3 <meta> in content, the result will be 2x3 repeated tags.
Case Studies
-
<replace css:theme="h2" css:content="h2" />
<h2 id="parent-fieldname-title" class="documentFirstHeading">Content Title</h2>
-
<after css:theme="h2" css:content="h2" />
<h2 class="highlight"><span class="keyword">Theme</span> Title</h2>
<h2 id="parent-fieldname-title" class="documentFirstHeading">Content Title</h2> -
<before css:theme="h2" css:content="h2" />
<h2 id="parent-fieldname-title" class="documentFirstHeading">Content Title</h2>
<h2 class="highlight"><span class="keyword">Theme</span> Title</h2> -
<merge attributes="class" css:theme="h2" css:content="h2" />
<h2 class="highlight documentFirstHeading"><span class="keyword">Theme</span> Title</h2>
-
<copy attributes="class id" css:theme="h2" css:content="h2" />
<h2 id="parent-fieldname-title" class="documentFirstHeading"><span class="keyword">Theme</span> Title</h2>
-
<replace css:theme-children="h2" css:content-children="h2" />
<h2 class="highlight">Content Title</h2>
<prepend theme="/html/body" content="/html/body/attribute::class" />
List
<nav class="main-menu">
<ul>
<li class="submenu">
<a href="#">Item 1</a>
<ul style="display: none;">
<li>
<a href"#">SubItem 1</a>
</li>
<ul id="portal-globalnav">
<li class="plain" id="portaltab-news">...</li>
<li class="plain" id="portaltab-events">
<a href="http://192.168.1.1:8080/mysite/events" class="plain">Events</a>
...
</ul>
<replace css:theme-children="nav.main-menu ul"> <xsl:for-each css:select="#portal-globalnav li"> <li class="submenu"><xsl:copy-of css:select="a" /></li> </xsl:for-each> </replace>
XPath
如果只是要本文的部份://div[@class="article-metaline"][last()]/following-sibling::text()
Replace href Attribute? Try Copy:
<copy attributes="href" css:content='#portal-logo' css:theme="#portal-logo" />
<copy attributes="href" theme="/html/body/div[2]/div[1]/div/div[1]/a" content="//*[@id='portal-logo']" /> <replace theme="/html/body/div[2]/div[1]/div/ul/li[1]/a" content="//*[@id='portaltab-index_html']/a" /> <replace theme="/html/body/div[2]/div[1]/div/ul/li[2]/a" content="//*[@id='portaltab-info']/a" /> <replace theme="/html/body/div[2]/div[1]/div/ul/li[3]/a" content="//*[@id='portaltab-article']/a" /> <replace theme="/html/body/div[2]/div[1]/div/ul/li[4]/a" content="//*[@id='portaltab-web']/a" />
被 JavaScript 特效影響的 HTML 片段,例如 Slider,必須使用未執行 JavaScript 前的 HTML 內容,來選取 XPath / CSS Selector 才會正確。
子目錄共用一組 Header,但首頁 Header 不同,方式之一是使用不同的 CSS ID 並透過 Rule 分別控制它們,可參考更多修改 CSS ID 範例。
<!-- change header's ID attribute --> <prepend css:theme="#header-index"> <xsl:attribute name="id">header-subpage</xsl:attribute> </prepend>
修改 Theme 裡的 <a href="" /> 屬性值,使用 <replace attributes="href" /> 可能沒有效果。
<copy attributes="href" theme="/html/body/div[2]/div[1]/div/div[1]/a" content="//*[@id='portal-logo']" />
Turbo Theming with XDV Example
<?xml version="1.0" encoding="UTF-8"?> <rules xmlns="http://namespaces.plone.org/xdv" xmlns:css="http://namespaces.plone.org/xdv+css"> <!-- Head: title --> <replace theme="/html/head/title" content="/html/head/title" /> <!-- Base tag --> <append theme="/html/head" content="/html/head/base" /> <!-- Body --> <prepend theme="/html/body" content="/html/body/attribute::class" /> <!-- Top level navigation --> <replace css:theme="#top-menu ul" css:content="ul#portal-globalnav" /> <!-- Search --> <replace css:theme="form#kbs" css:content="form#livesearch0" /> <!-- Breadcrumbs --> <copy css:theme=".bread_crumb" css:content="#portal-breadcrumbs > span:not(:first-child)" /> <!-- Page title --> <copy css:theme=".pages_textnews_news h2" content="//span[@id='breadcrumbs-1']//text()" /> <!-- Second level navigation --> <copy css:theme=".pages_sidenav_news" css:content="#portal-column-one dl.portletNavigationTree ul.navTreeLevel0 > *" /> <!-- Footer actions --> <replace css:theme="#footer_links ul" css:content="#portal-siteactions" /> </rules>
<rules xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<div id="top-menu"> <ul> <li><a class="current_home">Home</a></li> <li><a class="current_home_news_active">News</a></li> <li><a class="current_home_communicate">Transparency</a></li> <li><a class="current_home_meet">Meet the PM</a></li> <li><a class="current_home_history">History and Tour</a></li> <li><a class="current_home_nr10tv">Number 10 TV</a></li> </ul> </div>
<!-- Top level navigation - link class --> <xsl:template match="//ul[@id='portal-globalnav']//li/a"> <xsl:variable name="i"> <xsl:value-of select="1 + count(parent::*/preceding-sibling::*)"/> </xsl:variable> <xsl:variable name="hardcoded_class"> <xsl:choose> <xsl:when test="$i = 1">current_home</xsl:when> <xsl:when test="$i = 2">current_home_news</xsl:when> <xsl:when test="$i = 3">current_home_communicate</xsl:when> <xsl:when test="$i = 4">current_home_meet</xsl:when> <xsl:when test="$i = 5">current_home_history</xsl:when> <xsl:when test="$i = 6">current_home_nr10tv</xsl:when> <xsl:otherwise>current_home</xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="active"> <xsl:if test="parent::*[@class='selected']">_active</xsl:if> </xsl:variable> <xsl:copy> <xsl:copy-of select="@*"/> <xsl:attribute name="class"> <xsl:value-of select="$hardcoded_class"/><xsl:value-of select="$active" /> </xsl:attribute> <xsl:copy-of select="node()"/> </xsl:copy> </xsl:template>
- Let i = the current position in the list.
- Let hardcoded_class = the appropriate hardcoded class name, dependent on i.
- Let active = '_active' if the anchor's parent <li> has the class 'selected'
- Add a class attribute to the anchor with the value of hardcoded_class + active.
<!-- Page title --> <xsl:template match="//h1[contains(concat(' ', normalize-space(@class), ' '), ' documentFirstHeading ')]"> <h2 class="page_title_border"><xsl:copy-of select="./text()"/></h2> </xsl:template> <!-- Content --> <copy css:theme="#inner_container div:first-child" css:content="#portal-column-content > *:not(:first-child)" /> <!-- Drop junk content --> <drop css:theme="#skip_to_content" /> <drop css:theme="#rssholder" /> <drop css:theme="#inner_container div:not(:first-child)" /> <drop css:theme="#inner_container ~ div.navigation" /> <!-- Content class --> <xsl:template match="//div[@id='content']"> <div id='content' class='pages_post_news'> <xsl:apply-templates /> </div> </xsl:template>
通常不能直接用 *[@class='foo'] 來當作比對條件,因為它不能允許 <div class="foo bar"> 的情況,使用 *[contains(concat(' ', normalize-space(@class), ' '), ' foo ')]
這種複雜語法才行。
複製 skins/sunburst_styles/public.css 裡的部份內容到 demo.css,從 /* @group Status messages */ 到 /* @group Control panel */ 的前一行,併入下列的內容:
/* Hacks */ #edit-bar li { display: inline; } #inner_container div#edit-bar, #inner_container div#edit-bar div { padding-right: 0; } ul#content-views { margin: 0; padding: 0; } #top-menu { width: 71%; } form#searchGadget_form { margin-top: 1px; } /* One more from Sunburst: from @group Invisibles */ .hiddenStructure { display: block; background: transparent; background-image: none; /* safari bug */ border: none; height: 0.1em; overflow: hidden; padding: 0; margin: -0.1em 0 0 -0.1em; width: 1px; }
<?xml version="1.0"?> <object name="portal_css"> <stylesheet id="public.css" expression="not: request/HTTP_X_XDV | nothing" /> <stylesheet id="++resource++demo.css" title="" media="screen" rel="stylesheet" rendering="import" cacheable="False" compression="safe" cookable="False" enabled="1" expression="request/HTTP_X_XDV | nothing"/> </object>
Mockup
Live Search Box in Modal Overlay
<replace css:theme-children="#portal-searchbox" css:content-children="#portal-searchbox" />