独自テンプレートの作成 [Plone4.0]
ENG TOPIC VIEW
お知らせ表示として「日付+タイトル」一覧を表示するテンプレートを定義する。
お知らせ一覧のキーワード用タグ出力
お知らせ一覧表示テンプレートに、記事のカテゴリに応じた class 属性を出力して、カテゴリ別アイコンを表示できるようにする。
カテゴリは日本語で作成しているため、class 属性に付与するためには英数字にする必要がある。変換スクリプトとしてスキンフォルダに convert_category という名前で Python Script を作成する。key_dic に変換するカテゴリと、出力する文字列一覧の対応を定義しておく。また no_key にはキーワードが設定されていない場合に出力する文字列を定義しておく。
keywords = context.Subject()
# カテゴリ未定義
no_key = 'Nocategory'
# カテゴリ変換
key_dic = { 'お知らせ':'TopicsGeneral',
'入試情報(学部)':'TopicsAdmission',
'入試情報(大学院)':'TopicsAdmission',
'学生':'TopicsStudent',
'研究':'TopicsResearch',
'国際交流':'TopicsInternational' }
try:
for keyword in keywords:
if keyword in key_dic.keys():
return str(key_dic[keyword])
if context.Type() == 'Event':
return str('TopicsEvent')
return str(no_key)
except:
return str(no_key)
Topicタイプのビューとして ENG TOPIC VIEW を定義する
工学研究科のお知らせ表示用に、Topicタイプのビューを定義する。スキンフォルダ内にテンプレートを eng_topic_view として作成する。タイトルは「ENG TOPIC VIEW」とする。
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
lang="en"
metal:use-macro="context/main_template/macros/master"
i18n:domain="plone">
<body>
<metal:content-core fill-slot="content-core">
<metal:block define-macro="content-core"
tal:define="kssClassesView context/@@kss_field_decorator_view;
getKssClasses nocall:kssClassesView/getKssClassesInlineEditable;
templateId template/getId">
<div metal:define-macro="text-field-view"
id="parent-fieldname-text" class="stx"
tal:define="kss_class python:getKssClasses('text',
templateId=templateId, macro='text-field-view');
has_text exists:context/aq_explicit/getText;
text python:has_text and here.getText() or ''"
tal:condition="text"
tal:attributes="class python:test(context.Format() in ('text/structured',
'text/x-rst', ), 'stx' + kss_class, 'plain' + kss_class)">
<div metal:define-slot="inside" tal:replace="structure text">The body</div>
</div>
<tal:topiccontents define="b_size b_size | python:50;
topicContents python:here.queryCatalog(batch=True, b_size=b_size);
batch topicContents;">
<!-- Navigation -->
<div metal:use-macro="here/batch_macros/macros/navigation" />
<metal:listingmacro define-macro="listing">
<tal:listing condition="topicContents">
<div class="newsline" tal:define="toLocalizedTime nocall:context/@@plone/toLocalizedTime;">
<tal:items tal:repeat="obj topicContents">
<div class="tline">
<div tal:define="effective_date obj/EffectiveDate;
modification_date obj/ModificationDate;
effective_date python:test(effective_date != 'None', effective_date, modification_date);
effective_date python:here.toLocalizedTime(effective_date)"
class="date">
<span tal:replace="string:$effective_date">2007/11/11</span>
</div>
<div tal:define="cat python:obj.getObject().convert_category"
tal:attributes="class string:ctype-${cat};">
<a tal:attributes="href string:${obj/getURL};">
<tal:title tal:content="obj/pretty_title_or_id">title</tal:title>
</a>
<tal:event tal:condition="python:obj.Type=='Event'">
<span class="event_date">
<tal:date tal:define="event_start python:toLocalizedTime(obj.start, long_format=0);
event_end python:toLocalizedTime(obj.end, long_format=0);"
tal:replace="python:test(event_start==event_end, event_start, event_start+'-'+event_end)" />
<tal:title tal:condition="python:context.Language()=='ja'">開催</tal:title>
</span>
</tal:event>
<div tal:condition="python:checkPermission('Request review', obj.getObject())" tal:omit-tag="">
<span tal:attributes="class python:'state-' + str(obj.review_state)"
style="margin-left:5px; font-weight:bold; font-size:x-small;">
[<span i18n:translate="" tal:replace="python:here.portal_workflow.getTitleForStateOnType(obj.review_state, obj.portal_type)" />]
</span>
</div>
</div>
</div>
</tal:items>
</div>
</tal:listing>
</metal:listingmacro>
<p class="discreet"
tal:condition="python: not topicContents and here.listCriteria()"
tal:content="python:test(context.Language()=='ja', '掲載記事はありません。', 'There is currently no item to display.')">
</p>
<p class="discreet"
tal:condition="not: here/listCriteria"
i18n:domain="atcontenttypes"
i18n:translate="description_no_criteria_in_topic">
There are currently no criteria on which to search.
Please add them using the 'criteria' tab.
</p>
<!-- Navigation -->
<div metal:use-macro="here/batch_macros/macros/navigation" />
</tal:topiccontents>
</metal:block>
</metal:content-core>
</body>
</html>
Topicのビューで選択できるものを指定する
フォルダのビューで選択できるものを指定する。上で作成した、eng_topic_view も設定できるようにする。portal_types/Topic を開き Available view methods に次の行を追加する。
eng_topic_view
ENG BLOG VIEW
お知らせ表示として「日付+本文」一覧を表示するテンプレートを定義する。
各ページ内のURL変換スクリプトを定義する
ブログ表示するともとのページと Base URL が変更になるため、変換スクリプトを定義する。スキンフォルダに Python Script を transformRelatedURLs という名前で作成する。
# this is a quick hack
a_splitted = htmltext.split(' href="')
result = a_splitted[0]
for href in a_splitted[1:]:
if not href.startswith('http') and not href.startswith('/') and not href.startswith('file://') and not href.startswith('mailto:'):
result += ' href="' + base_url + '/../' + href
else:
result += ' href="' + href
htmltext = result
img_splitted = htmltext.split(' src="')
result = img_splitted[0]
for src in img_splitted[1:]:
if not src.startswith('http') and not src.startswith('/') and not src.startswith('file://'):
result += ' src="' + base_url + '/../' + src
else:
result += ' src="' + src
htmltext = result
return result
また Parameter List は次のように指定しておく。
Parameter List : htmltext, base_url
Topicタイプのビューとして ENG BLOG VIEW を定義する
工学研究科のお知らせ表示用に、Topicタイプのビューを定義する。スキンフォルダ内にテンプレートを eng_blog_view として作成する。タイトルは「ENG BLOG VIEW」とする。
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
lang="en"
metal:use-macro="context/main_template/macros/master"
i18n:domain="plone">
<body>
<metal:content-core fill-slot="content-core">
<metal:block define-macro="content-core"
tal:define="kssClassesView context/@@kss_field_decorator_view;
getKssClasses nocall:kssClassesView/getKssClassesInlineEditable;
templateId template/getId">
<div metal:define-macro="text-field-view"
id="parent-fieldname-text" class="stx"
tal:define="kss_class python:getKssClasses('text',
templateId=templateId, macro='text-field-view');
has_text exists:context/aq_explicit/getText;
text python:has_text and here.getText() or ''"
tal:condition="text"
tal:attributes="class python:test(context.Format() in ('text/structured',
'text/x-rst', ), 'stx' + kss_class, 'plain' + kss_class)">
<div metal:define-slot="inside" tal:replace="structure text">The body</div>
</div>
<tal:topiccontents define="b_size b_size | python:20;
topicContents python:here.queryCatalog(batch=True, b_size=b_size);
batch topicContents;">
<!-- Navigation -->
<div metal:use-macro="here/batch_macros/macros/navigation" />
<metal:listingmacro define-macro="listing">
<tal:listing condition="topicContents">
<div class="newsline" tal:define="toLocalizedTime nocall:context/@@plone/toLocalizedTime;">
<tal:items tal:repeat="obj topicContents">
<div class="bline">
<div tal:define="effective_date obj/EffectiveDate;
modification_date obj/ModificationDate;
effective_date python:test(effective_date != 'None', effective_date, modification_date);
effective_date python:here.toLocalizedTime(effective_date)"
class="date">
<span tal:replace="string:$effective_date">2007/11/11</span>
</div>
<div tal:define="translation python:obj.getObject();
base_url python:obj.getObject().absolute_url();"
tal:attributes="class string:ctype-${obj/portal_type};">
div class="blog_title">
<a tal:attributes="href string:${obj/getURL};">
<tal:title tal:content="obj/pretty_title_or_id">title</tal:title>
</a>
<tal:state tal:condition="python:checkPermission('Request review', obj.getObject())">
<span tal:attributes="class python:'state-' + str(obj.review_state)"
style="margin-left:5px; font-weight:bold; font-size:x-small;">
[<span i18n:translate="" tal:replace="python:here.portal_workflow.getTitleForStateOnType(obj.review_state, obj.portal_type)" />]
</span>
</tal:state>
</div>
<div tal:replace="structure python:here.transformRelatedURLs(translation.CookedBody(stx_level=2), base_url)" />
</div>
</div>
</tal:items>
</div>
</tal:listing>
</metal:listingmacro>
<p class="discreet"
tal:condition="python: not topicContents and here.listCriteria()"
tal:content="python:test(context.Language()=='ja', '掲載記事はありません。', 'There is currently no item to display.')">
</p>
<p class="discreet"
tal:condition="not: here/listCriteria"
i18n:domain="atcontenttypes"
i18n:translate="description_no_criteria_in_topic">
There are currently no criteria on which to search.
Please add them using the 'criteria' tab.
</p>
<!-- Navigation -->
<div metal:use-macro="here/batch_macros/macros/navigation" />
</tal:topiccontents>
</metal:block>
</metal:content-core>
</body>
</html>
Topicのビューで選択できるものを指定する
フォルダのビューで選択できるものを指定する。上で作成した、eng_blog_view も設定できるようにする。portal_types/Topic を開き Available view methods に次の行を追加する。
eng_blog_view
ENG TOPPAGE TOPIC VIEW
トップページ表示として、メインビジュアル、フリーエリア3か所、お知らせ一覧(日付+タイトル)を表示するテンプレートを作成する。
Topicタイプのビューとして ENG TOPPAGE TOPIC VIEW を定義する
工学研究科のトップページ表示用に、Topicタイプのビューを定義する。スキンフォルダ内にテンプレートを eng_toppage_topic_view として作成する。タイトルは「ENG TOPPAGE TOPIC VIEW」とする。
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
lang="en"
metal:use-macro="here/main_template/macros/master"
i18n:domain="plone">
<body>
<div metal:fill-slot="main">
<metal:main_macro define-macro="main">
<metal:body define-macro="body_macro"
tal:define="kssClassesView context/@@kss_field_decorator_view;
getKssClasses nocall:kssClassesView/getKssClassesInlineEditable;
templateId template/getId">
<div class="toppage">
<!--メインビジュアル-->
<div class="top_visual"
tal:define="id string:freearea0;
obj python:getattr(context.aq_parent, id, None);"
tal:condition="obj"
tal:attributes="class id">
<div tal:replace="structure python:here.transformRelatedURLs(obj.CookedBody(stx_level=2), obj.absolute_url())" />
<div tal:condition="python:context.portal_membership.checkPermission('Modify portal content', obj)" class="edit-link">
<a tal:attributes="href python:obj.absolute_url()+'/edit'" tal:content="string:Edit" i18n:translate="" />
</div>
</div>
<div class="top_area_one">
<!--フリーエリア1-->
<div tal:define="id string:freearea1;
obj python:getattr(context.aq_parent, id, None);"
tal:condition="obj"
tal:attributes="class id">
<div tal:replace="structure python:here.transformRelatedURLs(obj.CookedBody(stx_level=2), obj.absolute_url())" />
<div tal:condition="python:context.portal_membership.checkPermission('Modify portal content', obj)" class="edit-link">
<a tal:attributes="href python:obj.absolute_url()+'/edit'" tal:content="string:Edit" i18n:translate="" />
</div>
</div>
<!--お知らせ-->
<div tal:define="t_size python:context.itemCount and int(context.itemCount) or 10;" class="top_news" tal:condition="here/listCriteria | nothing">
<h2 tal:content="python:test(context.Language()=='ja', 'お知らせ', 'News')" />
<div class="rss"><a tal:attributes="href python:context.absolute_url() + '/RSS'">RSS</a></div>
<tal:topiccontents define="topicContents python:here.queryCatalog(sort_limit=t_size);">
<div metal:use-macro="here/eng_topic_view/macros/listing" />
</tal:topiccontents>
<div class="allnews">
<a tal:attributes="href string:../news"
tal:content="python:test(context.Language()=='ja', u'\u904e\u53bb\u4e00\u89a7', 'More')" />
</div>
</div>
</div>
<div class="top_area_two">
<!--フリーエリア2-->
<div tal:define="id string:freearea2;
obj python:getattr(context.aq_parent, id, None);"
tal:condition="obj"
tal:attributes="class id">
<div tal:replace="structure python:here.transformRelatedURLs(obj.CookedBody(stx_level=2), obj.absolute_url())" />
<div tal:condition="python:context.portal_membership.checkPermission('Modify portal content', obj)" class="edit-link">
<a tal:attributes="href python:obj.absolute_url()+'/edit'" tal:content="string:Edit" i18n:translate="" />
</div>
</div>
</div>
<div class="top_area_three">
<!--フリーエリア3-->
<div tal:define="id string:freearea3;
obj python:getattr(context.aq_parent, id, None);"
tal:condition="obj"
tal:attributes="class id">
<div tal:replace="structure python:here.transformRelatedURLs(obj.CookedBody(stx_level=2), obj.absolute_url())" />
<div tal:condition="python:context.portal_membership.checkPermission('Modify portal content', obj)" class="edit-link">
<a tal:attributes="href python:obj.absolute_url()+'/edit'" tal:content="string:Edit" i18n:translate="" />
</div>
</div>
</div>
</div>
</metal:body>
<div tal:replace="structure provider:plone.belowcontentbody" />
</metal:main_macro>
</div>
</body>
</html>
Topicのビューで選択できるものを指定する
フォルダのビューで選択できるものを指定する。上で作成した、eng_toppage_topic_view も設定できるようにする。portal_types/Topic を開き Available view methods に次の行を追加する。
eng_toppage_topic_view
ENG TOPPAGE BLOG VIEW
トップページ表示として、メインビジュアル、フリーエリア3か所、お知らせ一覧(日付+本文)を表示するテンプレートを作成する。
Topicタイプのビューとして ENG TOPPAGE BLOG VIEW を定義する
工学研究科のトップページ表示用に、Topicタイプのビューを定義する。スキンフォルダ内にテンプレートを eng_toppage_blog_view として作成する。タイトルは「ENG TOPPAGE BLOG VIEW」とする。
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
lang="en"
metal:use-macro="here/main_template/macros/master"
i18n:domain="plone">
<body>
<div metal:fill-slot="main">
<metal:main_macro define-macro="main">
<metal:body define-macro="body_macro"
tal:define="kssClassesView context/@@kss_field_decorator_view;
getKssClasses nocall:kssClassesView/getKssClassesInlineEditable;
templateId template/getId">
<div class="toppage">
<!--メインビジュアル-->
<div class="top_visual"
tal:define="id string:freearea0;
obj python:getattr(context.aq_parent, id, None);"
tal:condition="obj"
tal:attributes="class id">
<div tal:replace="structure python:here.transformRelatedURLs(obj.CookedBody(stx_level=2), obj.absolute_url())" />
<div tal:condition="python:context.portal_membership.checkPermission('Modify portal content', obj)" class="edit-link">
<a tal:attributes="href python:obj.absolute_url()+'/edit'" tal:content="string:Edit" i18n:translate="" />
</div>
</div>
<div class="top_area_one">
<!--フリーエリア1-->
<div tal:define="id string:freearea1;
obj python:getattr(context.aq_parent, id, None);"
tal:condition="obj"
tal:attributes="class id">
<div tal:replace="structure python:here.transformRelatedURLs(obj.CookedBody(stx_level=2), obj.absolute_url())" />
<div tal:condition="python:context.portal_membership.checkPermission('Modify portal content', obj)" class="edit-link">
<a tal:attributes="href python:obj.absolute_url()+'/edit'" tal:content="string:Edit" i18n:translate="" />
</div>
</div>
<!--お知らせ-->
<div tal:define="t_size python:context.itemCount and int(context.itemCount) or 5;" class="top_news" tal:condition="here/listCriteria | nothing">
<h2 tal:content="python:test(context.Language()=='ja', 'お知らせ', 'News')" />
<div class="rss"><a tal:attributes="href python:context.absolute_url() + '/RSS'">RSS</a></div>
<tal:topiccontents define="topicContents python:here.queryCatalog(sort_limit=t_size);">
<div metal:use-macro="here/eng_blog_view/macros/listing" />
</tal:topiccontents>
<div class="allnews">
<a tal:attributes="href string:../news"
tal:content="python:test(context.Language()=='ja', u'\u904e\u53bb\u4e00\u89a7', 'More')" />
</div>
</div>
</div>
<div class="top_area_two">
<!--フリーエリア2-->
<div tal:define="id string:freearea2;
obj python:getattr(context.aq_parent, id, None);"
tal:condition="obj"
tal:attributes="class id">
<div tal:replace="structure python:here.transformRelatedURLs(obj.CookedBody(stx_level=2), obj.absolute_url())" />
<div tal:condition="python:context.portal_membership.checkPermission('Modify portal content', obj)" class="edit-link">
<a tal:attributes="href python:obj.absolute_url()+'/edit'" tal:content="string:Edit" i18n:translate="" />
</div>
</div>
</div>
<div class="top_area_three">
<!--フリーエリア3-->
<div tal:define="id string:freearea3;
obj python:getattr(context.aq_parent, id, None);"
tal:condition="obj"
tal:attributes="class id">
<div tal:replace="structure python:here.transformRelatedURLs(obj.CookedBody(stx_level=2), obj.absolute_url())" />
<div tal:condition="python:context.portal_membership.checkPermission('Modify portal content', obj)" class="edit-link">
<a tal:attributes="href python:obj.absolute_url()+'/edit'" tal:content="string:Edit" i18n:translate="" />
</div>
</div>
</div>
</div>
</metal:body>
<div tal:replace="structure provider:plone.belowcontentbody" />
</metal:main_macro>
</div>
</body>
</html>
Topicのビューで選択できるものを指定する
フォルダのビューで選択できるものを指定する。上で作成した、eng_toppage_blog_view も設定できるようにする。portal_types/Topic を開き Available view methods に次の行を追加する。
eng_toppage_blog_view
ENG SITEMAP VIEW
サイトマップ用に指定したフォルダ内の index.html ページとフォルダタイプ一覧(キーワードの指定があればそのキーワードが指定されたフォルダのみ)を表示するマクロをテンプレートとして作成する。
サイトマップ用マクロ
テンプレート eng_sitemap を次のように作成し、テンプレート内にマクロ eng_sitemap を定義する。
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
i18n:domain="plone">
<body>
<dl metal:define-macro="eng_sitemap"
tal:define="query path;
subject subject | nothing;
subject python:test(subject, subject, '');
root python:context.portal_catalog.searchResults(
portal_type='Folder',
path = { 'query' : query, 'depth' : 0,});
results1 python:context.portal_catalog.searchResults(
id = 'index.html',
portal_type=['Document','Topic'],
path = { 'query' : query, 'depth' : 1,},);
results2 python:context.portal_catalog.searchResults(
portal_type='Folder',
path = { 'query' : query, 'depth' : 1,},
Subject = subject,
sort_on = 'getObjPositionInParent');
results python:results2 and results1+results2 or results2;"
tal:condition="python:root and results" tal:omit-tag="">
<div class="s-menu"
tal:define="title python:root[0].Title;">
<div class="s-menu-head">
<h2 tal:content="title">title</h2>
</div>
<ul class="s-menu">
<tal:items tal:repeat="item results">
<li>
<a tal:attributes="href string:${item/getURL};
class python:'sitemap-' + item.id;
title string:${item/Description}">
<span tal:replace="item/pretty_title_or_id">Title</span>
</a>
</li>
</tal:items>
</ul>
</div>
</dl>
</body>
</html>
Topicタイプのビューとして ENG SITEMAP VIEW を定義する
工学研究科のサイトマップ表示用に、Topicタイプのビューを定義する。スキンフォルダ内にテンプレートを eng_sitemap_view として作成する。タイトルは「ENG SITEMAP VIEW」とする。なお「ナビゲーションに表示しない」と設定したフォルダは表示されないようにする。また、コレクションのサブフォルダで検索された項目についてもサイトマップの項目として表示する。
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
lang="en"
metal:use-macro="here/main_template/macros/master"
i18n:domain="plone">
<body>
<div metal:fill-slot="main">
<metal:main_macro define-macro="main">
<metal:body define-macro="body_macro"
tal:define="kssClassesView context/@@kss_field_decorator_view;
getKssClasses nocall:kssClassesView/getKssClassesInlineEditable;
templateId template/getId">
<div tal:replace="structure provider:plone.abovecontenttitle" />
<h1 class="documentFirstHeading">
<metal:field use-macro="python:here.widget('title', mode='view')">
Title
</metal:field>
</h1>
<div tal:replace="structure provider:plone.belowcontenttitle" />
<p class="documentDescription">
<metal:field use-macro="python:here.widget('description', mode='view')">
Description
</metal:field>
</p>
<div tal:replace="structure provider:plone.abovecontentbody" />
<div metal:define-macro="text-field-view"
id="parent-fieldname-text" class="stx"
tal:define="kss_class python:getKssClasses('text',
templateId=templateId, macro='text-field-view');
text here/getText|nothing"
tal:condition="text"
tal:attributes="class python:test(here.Format() in ('text/structured',
'text/x-rst', ), 'stx' + kss_class, 'plain' + kss_class)">
<div metal:define-slot="inside" tal:replace="structure text">The body</div>
</div>
<div tal:attributes="class string:sitemap sitemap-${context/aq_parent/id}"
tal:define="sitemapContents python:here.queryCatalog(sort_on = 'getObjPositionInParent',
portal_type = 'Folder',
Subject='');
sorder python:0;">
<div tal:repeat="sitemapContent sitemapContents" tal:omit-tag="">
<div tal:define="path sitemapContent/getPath;
sorder repeat/sitemapContent/number"
tal:attributes="class python:'sitecategory sorder-'+str(sorder);
id string:sid-${sitemapContent/id};"
tal:condition="not: sitemapContent/exclude_from_nav">
<div tal:condition="python: 'Subject' in [crit.Field() for crit in context.listCriteria()]">
<div tal:define="crit python: context.getCriterion('crit__Subject_ATSelectionCriterion').getCriteriaItems()"
tal:condition="python: len(crit)">
<div tal:define="subject python: crit[0][1]['query']">
<div metal:use-macro="here/eng_sitemap/macros/eng_sitemap" />
</div>
</div>
</div>
<div tal:condition="python: not 'Subject' in [crit.Field() for crit in context.listCriteria()]">
<div metal:use-macro="here/eng_sitemap/macros/eng_sitemap" />
</div>
</div>
</div>
<div class="visualClear"><!-- --></div>
</div>
<div tal:define="results python:context.portal_catalog.searchResults( path = {'query' : '/'.join(context.getPhysicalPath()), 'depth' : 1,} );"
tal:omit-tag="">
<div tal:repeat="result results" tal:omit-tag="">
<div tal:attributes="class string:sub-sitemap-${result/id}"
tal:define="sitemapContents python:result.getObject().queryCatalog( sort_on = 'getObjPositionInParent', portal_type = 'Folder', Subject='');
sorder python:0;">
<div tal:content="result/Title" tal:attributes="class string:title-${result/id}" />
<div tal:repeat="sitemapContent sitemapContents" tal:omit-tag="">
<div tal:define="path sitemapContent/getPath;
sorder repeat/sitemapContent/number"
tal:attributes="class python:'sitecategory sorder-'+str(sorder);
id string:sid-${sitemapContent/id};"
tal:condition="not: sitemapContent/exclude_from_nav">
<div tal:condition="python: 'Subject' in [crit.Field() for crit in result.getObject().listCriteria()]">
<div tal:define="crit python: result.getObject().getCriterion('crit__Subject_ATSelectionCriterion').getCriteriaItems()"
tal:condition="python: len(crit)">
<div tal:define="subject python: crit[0][1]['query']">
<div metal:use-macro="here/eng_sitemap/macros/eng_sitemap" />
</div>
</div>
</div>
<div tal:condition="python: not 'Subject' in [crit.Field() for crit in result.getObject().listCriteria()]">
<div metal:use-macro="here/eng_sitemap/macros/eng_sitemap" />
</div>
</div>
</div>
<div class="visualClear"><!-- --></div>
</div>
</div>
</div>
<div class="visualClear"><!-- --></div>
</metal:body>
<div tal:replace="structure provider:plone.belowcontentbody" />
</metal:main_macro>
</div>
</body>
</html>
Topicのビューで選択できるものを指定する
フォルダのビューで選択できるものを指定する。上で作成した、eng_sitemap_view も設定できるようにする。portal_types/Topic を開き Available view methods に次の行を追加する。
eng_sitemap_view
ENG CALENDAR VIEW
年・月・日表示ができるイベントカレンダーをコレクションのビューとして作成する。利用方法はコレクションで表示するイベントタイプの検索条件(コンテンツタイプ、位置、日付など)を指定することを想定する。
週の文字列生成スクリプト
週の文字列を生成するスクリプト eng_calendar_weekstr をスキンレイヤ内に作成する。
from Products.CMFCore.utils import getToolByName
from Products.CMFPlone import PloneMessageFactory
translation_service = getToolByName(context, 'translation_service');
result_list = []
for i in xrange(7):
msgid = translation_service.day_msgid(i, format='a')
english = translation_service.weekday_english(i, format='a')
result_list.append(PloneMessageFactory(msgid, default=english))
return result_list
イベントリスト生成スクリプト
1ヶ月のイベントリスト生成スクリプト eng_calendar を次のように作成する。パラメータとしてリストを作成する年、月を渡す。
Parameter List
year, month
本体
end_date = container.portal_calendar.getNextMonth(month, year) - 1
last_day = end_date.day()
results = context.queryCatalog(
end = { 'query' : DateTime(year, month, 1, 0, 0), 'range' : 'min'},
start = { 'query' : DateTime(year, month, last_day, 23, 59), 'range' : 'max'},
sort_on = 'start',
)
event_list = []
for i in xrange(last_day):
day = i + 1
event_list.append({ 'day': day,
'week': DateTime(year, month, day).dow(),
'daily_events': [], })
for result in results:
if result.start.Date() == result.end.Date():
day = result.start.day()
event_list[day-1]['daily_events'].append( { 'title': result.Title,
'start': result.start,
'end': result.end,
'location': result.location,
'url': result.getURL(), } )
else:
if result.start < DateTime(year, month, 1, 0, 0):
day_begin = 1
else:
day_begin = result.start.day()
if result.end > DateTime(year, month, last_day, 23, 59):
day_end = last_day
else:
day_end = result.end.day()
for day in xrange(day_begin, day_end + 1):
event_list[day-1]['daily_events'].append( { 'title': result.Title,
'start': result.start,
'end': result.end,
'location': result.location,
'url': result.getURL(), } )
return event_list
カレンダーテンプレート
イベントカレンダーを表示するテンプレートを eng_calendar_view として次のように作成する。
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
lang="en"
metal:use-macro="here/main_template/macros/master"
i18n:domain="plone">
<body>
<div metal:fill-slot="main">
<metal:main_macro define-macro="main">
<metal:body define-macro="body_macro"
tal:define="kssClassesView context/@@kss_field_decorator_view;
getKssClasses nocall:kssClassesView/getKssClassesInlineEditable;
templateId template/getId">
<div tal:replace="structure provider:plone.abovecontenttitle" />
<h1 class="documentFirstHeading">
<metal:field use-macro="python:here.widget('title', mode='view')">
Title
</metal:field>
</h1>
<div tal:replace="structure provider:plone.belowcontenttitle" />
<p class="documentDescription">
<metal:field use-macro="python:here.widget('description', mode='view')">
Description
</metal:field>
</p>
<div tal:replace="structure provider:plone.abovecontentbody" />
<div tal:define="translation python:context.translation_service;
today python:DateTime();
month request/month | today/month;
month python:test(not request.has_key('month') and request.has_key('year'), 4, month);
month python:int(month);
day request/day | today/day;
day python:int(day);
orig_year request/year | today/year;
orig_year python:int(orig_year);
year python:month<4 and orig_year-1 or orig_year;
week_list python:context.eng_calendar_weekstr();
en_week_list python: [ translation.weekday_english(i, format='a') for i in range(0,7) ];
month_english python:translation.month_english(month);
event_list python:context.eng_calendar(orig_year, month);
base_url python:context.absolute_url();
msgfactory python:modules['Products.CMFPlone'].PloneMessageFactory;
param_year python:request.has_key('year');
param_month python:request.has_key('month');
param_day python:request.has_key('day');">
<!-- 年別タブ -->
<div tal:define="results python:context.queryCatalog( sort_on='start' );"
tal:condition="results">
<div id="year-tabs" tal:define="today_year today/year;
today_year python:int(today_year);
results python:context.queryCatalog( sort_on='start' );
month_begin python:test(results, results[0].start.month(), month);
year_begin python:test(results, results[0].start.year(), orig_year);
year_begin python:month_begin<4 and year_begin-1 or year_begin;
results python:context.queryCatalog( sort_on='end' );
month_end python:test(results, results[len(results)-1].end.month(), month);
year_end python:test(results, results[len(results)-1].end.year(), orig_year);
year_end python:month_end<4 and year_end-1 or year_end;">
<ul>
<tal:items tal:repeat="item python:xrange(year_begin, year_end+1)">
<li class="year-tab">
<a href="#"
tal:attributes="href python:base_url + '?year=' + str(item)">
<span tal:replace="python:str(item)" /><span tal:replace="python:test(context.Language() == 'ja', u'\u5e74\u5ea6', '')" />
</a>
</li>
</tal:items>
</ul>
</div>
</div>
<div class="visualClear"><!-- --></div>
<h2><span tal:replace="year" /> <span tal:replace="python:test(context.Language() == 'ja', u'\u5e74\u5ea6', u'Events')" /></h2>
<!-- 月別タブ -->
<div id="month-tabs" tal:define="month_list python:range(4,13) + range(1,4);"
tal:condition="python:not param_year or param_month or param_day">
<ul>
<tal:item repeat="month_num month_list">
<li class="month-tab"
tal:define="tab_year python:test(month_num<4, year+1, year)"
tal:attributes="class python:(month_num == month and 'active ' or '') + 'month_tab'">
<a href="#"
tal:attributes="href python:base_url + '?year=' + str(tab_year) + '&month=' + str(month_num);">
<span tal:define="english python:translation.month_english(month_num);
msgid python:translation.month_msgid(month_num);
msg python:msgfactory(msgid, default=english);"
tal:replace="msg">
April
</span>
</a>
</li>
</tal:item>
</ul>
</div>
<!-- 月カレンダーのヘッダ -->
<div id="calendar_header"
tal:condition="python:not param_day and (param_month or not param_year)">
<div id="april-logo" class="month-logo"
tal:attributes="id python:month_english.lower() + '-logo';
class string:month-logo;">
<img tal:attributes="src python:month_english.lower() + '-logo.jpg';
alt python:month_english;" />
</div>
<div id="april-picture" class="month-picture"
tal:attributes="id python:month_english.lower() + '-picture';
class string:month-picture;">
<img tal:attributes="src python:month_english.lower() + '-picture.jpg';" />
</div>
</div>
<!-- 月カレンダーのカレンダー部 -->
<table id="current_month_events"
tal:condition="python:not param_day and (param_month or not param_year)">
<tal:item tal:repeat="item event_list">
<tr class="event_item"
tal:define="week_str python:week_list[item['week']];
en_week_str python:en_week_list[item['week']].lower();"
tal:attributes="class python:'event_item week_' + en_week_str; ">
<td class="day">
<a href="#"
tal:omit-tag="python:not item['daily_events']"
tal:attributes="href python:base_url + '?year=' + str(orig_year) + '&month=' + str(month) + '&day=' + str(item['day'])">
<span tal:replace="python:item['day']">1</span>
</a>
</td>
<td class="week">
<span tal:content="week_str">Mon</span>
</td>
<td class="event_of_day">
<ul tal:condition="item/daily_events">
<li tal:repeat="event item/daily_events">
<a href="#" tal:attributes="href event/url">
<span tal:replace="event/title" />
</a>
</li>
</ul>
</td>
</tr>
</tal:item>
</table>
<!-- 日カレンダーのヘッダ -->
<div tal:condition="python:param_day">
<div id="calendar_header"
tal:define="msgid python:translation.month_msgid(month);
english python:translation.month_english(month);
month_msg python:msgfactory(msgid, default=english);
week_num python:event_list[day-1]['week'];
week_msgid python:translation.day_msgid(week_num);
week_english python:translation.weekday_english(week_num);
week_msg python:msgfactory(week_msgid, default=week_english);">
<div class="current-date">
<div class="today" tal:condition="python:context.Language() == 'ja'">
<span class="month" tal:content="month_msg" />
<span class="day" tal:content="python:str(day)">28</span><tal:date tal:replace="python:u'\u65e5'" />
<span class="weekday" tal:content="week_msg" />
</div>
<div class="today" tal:condition="python:context.Language() != 'ja'">
<span class="weekday" tal:content="week_msg">Monday</span>,
<span class="month" tal:content="month_msg">April</span>
<span class="day" tal:content="python:str(day)">28</span>
</div>
</div>
<div id="current_month_calendar" class="event_calendar">
<div id="calendar_month">
<span tal:replace="month_msg">March</span>
</div>
<table>
<tr>
<td class="weekday_sun" i18n:translate="weekday_sun_short">Su</td>
<td class="weekday_mon" i18n:translate="weekday_mon_short">Mo</td>
<td class="weekday_tue" i18n:translate="weekday_tue_short">Tu</td>
<td class="weekday_wed" i18n:translate="weekday_wed_short">We</td>
<td class="weekday_thu" i18n:translate="weekday_thu_short">Th</td>
<td class="weekday_fri" i18n:translate="weekday_fri_short">Fr</td>
<td class="weekday_sat" i18n:translate="weekday_sat_short">Sa</td>
</tr>
<tr tal:define="first_week python:event_list[0]['week'];
week_num python:len(event_list) + first_week;
week_num python:test(week_num%7, int(week_num/7)+1, int(week_num/7));"
tal:repeat="week python:xrange(week_num)">
<tal:item repeat="date python:xrange(week*7-first_week+1, week*7-first_week+8)">
<td tal:condition="python:date>0 and date<=len(event_list)"
tal:attributes="class python:event_list[date-1]['daily_events'] and 'event' or 'no_event';">
<a href="#"
tal:omit-tag="python:not event_list[date-1]['daily_events']"
tal:attributes="href python:base_url + '?year=' + str(orig_year) + '&month=' + str(month) + '&day=' + str(date);">
<span tal:replace="python:str(date)">1</span>
</a>
</td>
<td tal:condition="python:not (date>0 and date<=len(event_list))" />
</tal:item>
</tr>
</table>
</div>
</div>
</div>
<!-- 日カレンダー -->
<div id="day_events" tal:condition="python:param_day">
<div class="no_event_today"
tal:condition="python:not event_list[day-1]['daily_events']"
tal:content="python:test(context.Language() == 'ja', u'\u672c\u65e5\u958b\u50ac\u4e88\u5b9a\u306e\u30a4\u30d9\u30f3\u30c8\u306f\u3042\u308a\u307e\u305b\u3093\u3002', 'No Events Today.')"></div>
<table id="today_events" tal:condition="python:event_list[day-1]['daily_events']">
<tr class="day_list_header">
<th class="event_title"
tal:content="python:context.Language()=='ja' and u'\u884c\u4e8b\u540d' or 'Event'">Event</th>
<th class="event_when"
tal:content="python:context.Language()=='ja' and u'\u65e5\u6642\u30fb\u5834\u6240' or 'Date/Time, Location'">Date/Time</th>
</tr>
<tal:item tal:repeat="item python:event_list[day-1]['daily_events']">
<tr class="event_item">
<td class="event_title">
<a href="#" tal:attributes="href item/url;" tal:content="item/title" />
</td>
<td class="event_when"
tal:define="start_date item/start/Date;
end_date item/end/Date;">
<div tal:condition="python:start_date == end_date" tal:omit-tag="">
<span tal:content="item/start/TimeMinutes">3:10</span> -
<span tal:content="item/end/TimeMinutes"
tal:condition="python:item['start'] != item['end']">5:45</span>
<br /><span tal:content="item/location" />
</div>
<div tal:condition="python:start_date != end_date" tal:omit-tag=""
tal:define="notime python:test(item['start'].TimeMinutes()=='00:00' and item['end'].TimeMinutes()=='00:00', True, False)">
<span tal:content="python:item['start'].Date() + test(notime, '', ' ' + item['start'].TimeMinutes())">3:10</span> -
<span tal:content="python:item['end'].Date() + test(notime, '', ' ' + item['end'].TimeMinutes())">5:45</span>
<br /><span tal:content="item/location" />
</div>
</td>
</tr>
</tal:item>
</table>
</div>
<!-- 年カレンダー -->
<div class="year-page" tal:condition="python:param_year and not param_month and not param_day">
<div tal:define="month_list python:range(4,13) + range(1,4);"
tal:repeat="month month_list" tal:omit-tag="">
<div tal:define="tab_year python:test(month<4, year+1, year);
english python:translation.month_english(month, format='a').lower();"
tal:attributes="class python:'calendar-item calendar-' + english;">
<div class="year" tal:content="tab_year" />
<div class="month">
<a href="#"
tal:attributes="href python:base_url + '?year=' + str(tab_year) + '&month=' + str(month);"
tal:content="month">1</a>
</div>
<table tal:define="msgid python:translation.month_msgid(month);
english python:translation.month_english(month);
month_msg python:msgfactory(msgid, default=english);
event_list python:context.eng_calendar(tab_year, month);">
<tr class="week_head">
<td class="weekday_sun" i18n:translate="weekday_sun_short">Su</td>
<td class="weekday_mon" i18n:translate="weekday_mon_short">Mo</td>
<td class="weekday_tue" i18n:translate="weekday_tue_short">Tu</td>
<td class="weekday_wed" i18n:translate="weekday_wed_short">We</td>
<td class="weekday_thu" i18n:translate="weekday_thu_short">Th</td>
<td class="weekday_fri" i18n:translate="weekday_fri_short">Fr</td>
<td class="weekday_sat" i18n:translate="weekday_sat_short">Sa</td>
</tr>
<tr tal:define="first_week python:event_list[0]['week'];
week_num python:len(event_list) + first_week;
week_num python:test(week_num%7, int(week_num/7)+1, int(week_num/7));"
tal:repeat="week python:xrange(week_num)">
<tal:item repeat="date python:xrange(week*7-first_week+1, week*7-first_week+8)">
<td tal:condition="python:date>0 and date<=len(event_list)"
tal:attributes="class python:event_list[date-1]['daily_events'] and 'event' or 'no_event';">
<a href="#"
tal:omit-tag="python:not event_list[date-1]['daily_events']"
tal:attributes="href python:base_url + '?year=' + str(tab_year) + '&month=' + str(month) + '&day=' + str(date);">
<span tal:replace="python:str(date)">1</span>
</a>
</td>
<td tal:condition="python:not (date>0 and date<=len(event_list))" />
</tal:item>
</tr>
</table>
</div>
<div class="visualClear"
tal:condition="python: month % 3 == 0"><!-- --></div>
</div>
</div>
</div>
</metal:body>
</metal:main_macro>
</div>
</body>
</html>
画像
デザイン用の各月の画像などを同じレイヤに作成する。
イベントのXML出力
他のサイトとのイベント連携も可能となるよう XML 出力もできるようにしておく。ページテンプレートとしてスキンフォルダに eng_events_xml を追加する。追加したテンプレートの Properties タブより content_type を次のように変更する。
content_type : text/xml
テンプレートは次のように定義する。
<?xml version="1.0" encoding="UTF-8" ?>
<items xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
xmlns:metal="http://xml.zope.org/namespaces/metal"
tal:define="year request/year;
year python:int(year);
month request/month;
month python:int(month);
end_date python:context.portal_calendar.getNextMonth(month, year) - 1;
last_day python:end_date.day();
results python:here.queryCatalog(
end = { 'query' : DateTime(year, month, 1, 0, 0), 'range' : 'min'},
start = { 'query' : DateTime(year, month, last_day, 23, 59), 'range' : 'max'},
sort_on = 'start')">
<item tal:repeat="result results">
<url tal:content="python:result.getObject().absolute_url()" />
<title tal:content="result/Title" />
<location tal:content="result/location" />
<start tal:content="result/start" />
<end tal:content="result/end" />
</item>
</items>
呼び出すには year と month を指定して次のように行う。これで指定した月のイベント一覧を出力できる。
http://イベントカレンダー用コレクションのURL/eng_events_xml?year=2009&month=4
Topicのビューで選択できるものを指定する
フォルダのビューで選択できるものを指定する。上で作成した、eng_calendar_view も設定できるようにする。portal_types/Topic を開き Available view methods に次の行を追加する。
eng_calendar_view
