The way we recommend to use erp5_web is to:
- take an existing 'standard' HTML design
- refactor the HTML / CSS with TAL, METAL and widgets to create a new erp5_theme
Table of Contents
Details¶
erp5_web is designed to make this process as quick as possible. It is ideal to
work in collaboration with graphic designers and Web agencies which do not need
to know about the details of ERP5 or erp5_web. It is also ideal to create a
unique design for every site or every client.
This approach is different from the approach of certain CMS which rather focus
on providing a very generic and hopefully universal layout which can be somehow
tweaked through CSS. People interested in a minimal universal layout can have a
look a erp5_minimal_theme, which is currently more intended for developers and
test rather than for real use in commercial Web sites.
In the remaining of this How To, we are going to explain how we created
erp5_multiflex5_theme business template.
Before proceeding further, make sure you read:
- ERP5 XHTML Style (Free Subscription) which explains the rendering process of ERP5
- ERP5 Web (Free Subscription) which explains the architecture of ERP5 Web
Upload Static Files¶
The
Multiflex5 theme is a public domain theme created by Gerhard of 1234.info.
The first step consists of creating a new folder in portal_skins and uploading
all static files provided by the designer into that folder.
The files which must be uploaded include:
- images (as Image object - use WebDAV if you have many images to upload, but not for the other file types since it would create DTML Page objects instead of Page Template objects)
- CSS (as Page Template object)
- HTML (as Page Template object)
- JS (as Page Template object)
Do not forget to add:
at the head of CSS. This is required to make sure that the CSS Page Template is
considered as a CSS file by Web Browsers. Add a similar instruction for JS files
or for any Text based Page Template which is not HTML.
Use a non ambiguous namespace for images (ie. do not user img for example but
multiflex5_image) so that it is possible to mix multiple Web themes within a
single site yet use caching. But remember that the CSS files may have references
to the image folder: don't forget to rename it in the CSS files too.
Create the default main template files¶
Our goal is to create an empty layout which can be fed with:
- content (the content of the pages, forms)
- widgets (ie. building blocks of the page)
- gadgets (ie. drag & dropable boxes, actually implemented as a widget)
There are 2 possible ways:
- monolithic Page Template with TAL and METAL macros to create dynamic content and include widgets or gadgets (best for speed)
- use of ERP5 native widget system (best for modularity but caching is required for speed)
The 2 approaches can be combined.
Let us try the "widget" approach. We need to create an ERP5 Form:
erp5_web_multiflex5_layout
The page template of this form should be set in the Setting tab to:
template_erp5_web_multiflex5
Let us rename and add a few groups (Order Tab)
bottom
right sidemenu1 (Subsection List)
The logical structure and building blocks of the page will appear in the end in:
erp5_web_multiflex5_layout
while
template_erp5_web_multiflex5
will only be used to include each block defined in erp5_web_multiflex5_layout into the HTML code
Now, we are going to create the file:
template_erp5_web_multiflex5
It is a Page Template that we will later fill with all the code needed to build the page.
Create a skin¶
In Zope CMF, a skin will define which folders from the Skins Tool are used to fetch
everything related to a theme : the CSS files, the templates, the static images...
Each skin is made of several layers, each layer being a folder in the portal_skins tool.
In order to be able to use the new theme, you will have to add a new skin in portal_skins, and use it.
- Go to the portal_skins tool
- Go to the tab Properties
- Type in a new skin name, multiflex5, and layers.You will have to include several layers like erp5_xhtml_style, erp5_core... The first item in this list has to be the name of the folder you created in the portal_skins. After filling in these two fields, add the skin.
Create a Web Site instance¶
Go to Web Site module. Add a Web Site.
Define the default layouts (Container and Content) to
erp5_web_multiflex5_layout
Define the Skin name to:
multiflex5
Rename the ID of the website to:
multiflex5_test
Create a Web Page with some content. Let us suppose this page is:
web_page_module/1
Then go to the URL:
web_site_module/multiflex5_test/web_page_module/1
At this stage, you will likely get an error. Our goal now is to make sure
the content of the web page is display in the right location.
use-setup-web-theme¶
template_erp5_xhtml_style is the mother HTML Template of anything in ERP5.
It defines a "layout" slot where you will inject the
part of your Page
Template. Everything else exists only for theme designers.
You will have to insert the following code in your page template body in order to
insert it in the slot. This code defines a couple of useful variables and,
more important, tells template_erp5_xhtml_style which javascripts and CSS
to embed in addition to other JS and CSS which are embedded by default.
<body>
<tal:block metal:define-macro="master">
<tal:block tal:define="website here/getWebSiteValue;
enctype string:multipart/form-data;
portal_path python:website.absolute_url();
current_main_section here/WebSite_getMainSection;
editable request/editable_mode | python: 0;
list_mode list_mode | nothing;
dialog_mode dialog_mode | nothing;
has_no_layout python: layout_form is None;
dummy python: request.set('dialog_mode', dialog_mode);
dummy python: request.set('list_mode', list_mode);
global css_list_template python:[
'%s/mf54_reset.css' % portal_path,
'%s/mf54_grid.css' % portal_path,
'%s/mf54_content.css' % portal_path,
];
global js_list python:[
'%s/erp5_tabber.js' % portal_path,
]">
<tal:block metal:use-macro="here/template_erp5_xhtml_style/macros/master">
<tal:block metal:fill-slot="layout">
<!-- INSERT HERE THE CODE THAT WILL BE INJECTED IN THE LAYOUT SLOT -->
</tal:block>
</tal:block>
</tal:block>
</tal:block>
</body>
The code to insert in the layout slot is the static code of one of the Multiflex5
templates, found in its HTML files.
After injecting this code, you'll be able to display the static layout with no dynamic content.
Note that all the headers of the HTML are managed by template_erp5_xhtml_style.
template_erp5_xhtml_style should be rich enough to cover all possible cases.
If this is not the case, try to extend it in a generic way and contribute to
erp5_xhtml_style core. If what you want to do is very specific, you can consider
making your own version of template_erp5_xhtml_style although this is not
recommended for maintenance.
Add the "content" slot¶
Find out in the static code the location which can be considered as "content".
Then erase and replace with a METAL expression like this:
<!-- C. MAIN SECTION -->
<div class="main">
<h1 class="pagetitle">Content Toolbox (With sidebar)</h1>
<!-- C.1 CONTENT -->
<div class="main_content">
<div class="corner-content-1col-top"></div>
<div class="content-1col-nobox">
<tal:block metal:define-slot="main"/>
</div>
<div class="corner-content-1col-bottom"></div>
</div>
(You can notice that the class name has been renamed to main_content. It is
required to rename a few CSS class names (content, document...) in order to
prevent any conflict between the web theme originated HTML code and the ERP5-generated
HTML code)
From now on, the METAL expression will be replaced with the content generated
by ERP5 Forms. Let us look at an example showing how the metal expression is
replaced and what the content looks like:
<!-- C.1 CONTENT -->
<div class="main_content">
<div class="corner-content-1col-top"></div>
<div class="content-1col-nobox">
<div class="document">
<div class="content">
<fieldset id="fieldset_webcontent_header_bottom" class="webcontent header bottom">
<div title="" class="field headline">
<label>Title </label>
<div class="input"><span class="headline">10</span></div>
</div>
</fieldset>
<fieldset id="fieldset_bottom" class="bottom">
<div title="" class="field page hiddenLabel">
<label>Page Content</label>
<div class="input">
<h1>1-03. Text</h1>
<h5>Paragraph</h5>
<p>Standard text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text</p>
</div>
</div>
</fieldset>
<p class="clear"/>
</div>
<div class="corner-content-1col-bottom"></div>
</div>
As we can see the content generated by ERP5 add two embedded divs:
<div class="document">
<div class="content">
</div>
</div>
Inside the content div, all forms are rendered using a structure which combines the following tags:
fieldset
legend
label
The rendering of Web Page uses 2 fields:
- one to display the title
- one to display the content of the page
However, it is well know that certain Web layouts consider the title of a Page
as part of the layout while others consider as part of content. For this reason,
in order to help CSS authors to display or hide that information, the following
classes were defined in ERP5 :
All this code is generated automatically by erp5_xhtml_style and form_render. It is not a good idea to change it.
If you have a problem of CSS class name conflict (for instance on the "content" class), rename the classes of the Web theme rather than those of erp5_xhtml_style.
Define widget structure one by one¶
First of all, look at the page and name the different groups.
Example:
- header: a header which can contain multiple subgroups (ex. header_top, header_bottom)
- top: an area which is at the top of the content area, under the header
- headline: an are which is at the top of the content itself, within the content area
- left: an area with boxes at the left of the content area
- right: an area with boxes at the right of the content area
- footer: an area under the content area
Next, extend the variable definition in:
template_erp5_web_multiflex5
with:
aggregate python: has_no_layout or layout_form.Form_getGroupList(
['header', 'top', 'headline', 'subcontent', 'footer']);
aggregate python: ((aggregate is not has_no_layout) and dict(aggregate)) or {};
header_area python:aggregate.get('header', []);
top_area python:aggregate.get('top', []);
headline_area python:aggregate.get('headline', []);
subcontent_area python:aggregate.get('subcontent', []);
footer_area python:aggregate.get('footer', []);
The goal here is to define the different aggregate groups to use to fill the page.
Then add the following line to render the area named 'subcontent':
<!-- Layout form rendering -->
<tal:block tal:condition="python: layout_form is not None">
<tal:block metal:use-macro="here/aggregate_render/macros/aggregate_populate_request"/>
<tal:block tal:repeat="aggregate python: [('subcontent', subcontent_area)]">
<tal:block metal:use-macro="here/aggregate_render/macros/aggregate_render"/>
</tal:block>
</tal:block>
Then move HTML code from the static page to the layout form:
erp5_web_multiflex5_layout
The idea is to create an "Editor Field" then set:
editable = False
display = True
and fill the "Default" value with static HTML code which is going to be replaced later with dynamic code.
Create dynamic content for widgets¶
Create a new field and associated Widget renderer in the form of a Page Template:
WebSection_viewSubsectionWidget
Here is an example of code for a Widget:
<tal:block replace="nothing">
<!--
This widget displays the list of Sections contained in the current context.
TODO:
* make sure translation is possible
* make sure URLs are correct
* use generic method (erp5_web) to retrieve the list of subsections
* make it hierarchic
-->
</tal:block>
<ul tal:define="current_web_section python:request.get('current_web_section', here)">
<li tal:repeat="subsection python:current_web_section.WebSection_getSiteMapTree(depth=1)"><a href="#" tal:content="subsection/translated_title"
tal:attributes="href subsection/url">Menu item</a></li>
</ul>
Please watch here how we use the request to retrieve the rendering environment.
This is where we should find the current document, current context, current
section, etc. It helps accelerating rendering.
Add dynamic parameters to the CSS Page Template¶
Add the following kind of code at the head the CSS:
<tal:block define="dummy python: request.RESPONSE.setHeader('Content-Type', 'text/css;; charset=utf-8')"/>
<tal:block define="
site_url python:here.absolute_url();
body_color python:here.getLayoutProperty('layout_body_color', 'rgb(240,240,240)');
primary_color python:here.getLayoutProperty('layout_primary_color', 'rgb(200,200,200)');
secondary_color python:here.getLayoutProperty('layout_secondary_color', 'rgb(225,225,225)');
header_color python:here.getLayoutProperty('layout_header_color', 'rgb(218,218,218)');
menu_color python:here.getLayoutProperty('layout_menu_color', 'rgb(235,235,235)');
container_width python:here.getLayoutProperty('layout_container_width', 978);
border_width python:here.getLayoutProperty('layout_border_width', 10);
content_width python:container_width - 2 * border_width;
header_background_image python:here.getLayoutProperty('layout_header_background_image',
'mf54_image/bg_header.jpg');
header_background_image python:'%s/%s' % (site_url, header_background_image);
">
<!-- Original CSS code goes here -->
</tal:block>
and make every CSS dynamic such as in:
.header {width:px; min-height:130px /*Non-IE6*/; height:auto !important /*Non-IE6*/; height:130px /*IE6*/; border-left:solid px ; border-right:solid px ; background: url() repeat-x /*Total header background image entered here. Height: 125px*/; font-size:1.0em;}
The idea is to make the following items configurable:
- width
- colors
- images
- choice of fonts
For this, you will have to create too a form named
WebSection_viewMythemeConfiguration
and define all required field in this form. In our example:
- layout_body_color
- layout_primary_color
- layout_secondary_color
- layout_header_color
- layout_menu_color
- layout_container_width
- layout_border_width
- layout_header_background_image
Related Articles¶