Skip to content. | Skip to navigation

Personal tools

Navigation

You are here: Home / Tutorial / Diazo By Example

Diazo By Example

Simple Diazo Rule Snippets

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

<h2 class="highlight"><span class="keyword">Theme</span> Title</h2>
<h2 id="parent-fieldname-title" class="documentFirstHeading">Content Title</h2>
  • <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

Unordered 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

Find Link URL by Link Text

如果只是要本文的部份://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>
  1. Let i = the current position in the list.
  2. Let hardcoded_class = the appropriate hardcoded class name, dependent on i.
  3. Let active = '_active' if the anchor's parent <li> has the class 'selected'
  4. 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" />