SilvaLayout

Introduction

SilvaLayout contains user interface components to develop your own Silva public website layouts. It extends Silva so that it becomes possible to select entirely different skins for different parts of a website. It focuses on making the creation, deployment and maintenance of complicated skins manageable.

It does not invent its own new technology to do so. Instead, it does this by Zope 3 technologies through Five. Five is a system that allows developers to use Zope 3 technology within Zope 2. Zope 3 and Five are bundled with Zope 2.

For installation instructions see the INSTALL.txt.

Using it from Silva

Using the Silva UI (SMI), navigate to the properties tab for Silva root. Press the 'settings' button to view the layout settings. On this screen you can select a skin from the list of skins that are currently installed into your Zope setup.

To view the skin, click 'view public version' in the lower right corner and the content will become visible in the selected skin. You can select different skins in each publication in the site.

Creating new layouts

A layout package is a Zope product that typically consists of a combination of HTML templates, resources such as images and javascript files, and of view related behavior expressed as Python code in Python module. You can place all files in one directory, or, when there are many files, organize it in a number of subdirectories - whatever best suits your project.

Creating skins

If you want to create new skins, you can do this in a your own Zope extension, called a Zope product. You can add as many skins in a single Zope product as you like, or alternatively use a new Zope product for each skin. A SilvaLayout based Zope product functions as a Silva extension which adds its skins to any Silva that exists in that Zope installation.

How to create a SilvaLayout based product

  • create a new product to be placed in the Zope Products directory; you can base this on the SilvaLayoutTemplate product in the SilvaLayout/examples directory if you like.

    A Zope product is a directory that needs at least an (empty) __init__.py file. This is needed so that Python can recognize the product as an package, and Zope can recognize it as a product (zope extension).

  • create a configure.zcml file in this directory. This hooks templates together using Zope Configuration Markup Language into a skin. Zope will automatically pick up the configure.zcml file in your product.

  • A skin consists of one or more layers. When using SilvaLayout, your skin consists of at least your own layer, and the silvadefault layer, as well as the basic zope default layer.

    Having such multiple layers is very powerful, if you want to reuse bits of layout in multiple other layouts, or want to build a layout based on another layout but overriding pieces of it; you can reuse the same layer in multiple layouts.

  • Let's define a layer in ZCML. A layer consists of one or more view and/or resource definitions:

    <!-- we are creating a layer called mylayer -->
    <browser:layer
      name="mylayer"
      />
    
    <!-- we define the standard template for all Silva containers for
         mylayer. This defines a 'view' -->
    <browser:page
      name="index.html"
      for="silva.core.interfaces.IContainer"
      class="Products.SilvaLayout.browser.views.Container"
      template="maintemplate.pt"
      permission="zope2.View"
      layer="mylayer"
      />
    
    <!-- we also make sure all images in the directory 'images'
         are available to our layer -->
    <browser:resourceDirectory
      name="images"
      directory="images"
      permission="zope2.View"
      layer="mylayer"
      />
    
    <!-- now we define the skin and of which layers it consists -->
    <browser:skin
      name="myskin"
      layers="mylayer silvadefault default"
      />
    
  • browser:page - this ZCML directive is used to define a view.

    The name attribute determines under which name the view will be available through the web. index.html is the name used when looking at an object without specifying an explicit view.

    The for attribute specifies for which interfaces the view will be used; in the example the view is defined for any Silva container, such as a Folder or a Publication. The interface is a so-called "dotted name". Internally such a name refers to a piece of code in a Python module (in this case to the IContainer interface definition in the interfaces.py module in the Silva package), but you can treat it just as an opaque name. We'll give a listing of some useful interfaces below.

    With template the Zope Page Template is specified which will be used for rendering the container a HTML.

    The optional class attribute specifies a Python class in a Python module. You see that the class is also defined using a dotted name. This class is called a view class. It offers an API which can be useful from within the template to help rendering the view. (see below for examples). In SilvaLayout, a number of useful view classes are exposed which you will likely want to use. Some you'll use as a base class for your own public view; others help with particular purposes, such as tree generation and the generation of absolute URLs for objects - you will sometimes want to override these for your own objects.

    The permission attribute determines what permission a user needs to access this page. This depends on the user's role in the location in Silva the user is trying to view. For SilvaLayout, normally zope2.View is the right permission to use.

  • The browser:resourceDirectory directive makes all the resources in the subdirectory images accessible through URLs.

  • The browser:skin directive defines a skin. A skin defines the layout of a particular section of a Silva site, and is what can be selected from the Silva UI for a particular publication (or the Silva Root).

    It consists of the mylayer layer, in which it will look first for defined views such as pages. If a specific view can not found in there, it will look in the silvadefault layer, and if it still cannot be found, it will look in the standard Zope default layer. If the view still cannot be found, the system will give an error -- the user likely is trying to access Silva through a URL that does not exist.

Zope 3 and SilvaLayout for designers

Zope 3 (and Five, exposing it to Zope 2) are of course large topics. If you are a programmer we recommend you look at the material available on the web, or the various Zope 3 books. Here we try to give you a short introduction with just the basics for designers. We are assuming you're familiar with the types of objects in Silva, and are familiar with Zope Page Templates (ZPT), Zope's page templating language.

ZPTs in Zope 3 are the same as those in Zope 2. They however do expose some extra names you can use, in particular context and view.

context is the content object in Silva (such as a Document or Folder) that the user is currently viewing through this template. You can call methods on it defined in the standard Silva API. This is very similar to the way here works in ZPTs in non-Five Zope 2. For example:

context/get_title

view exposes the view API. A view API is very similar to the content object API, but exposes extra view-related API. They for instance offer a convenience method to access Silva metadata easily from your layout (see below).

Methods on views typically implement complicated view functionality in efficient python, which can then be used inside your ZPT template. If you are not a Python programmer, you'll have to find one and tell them what you would like to have on your view API. Once written, it can be hooked into your views using the class attribute on your page directive.

For instance, the standard SilvaLayout.browser.silvaview.SilvaView has has a method 'title' that can be called like this in a TALES expression:

view/title

Access to Silva metadata fields has never been easier with the SilvaView base class:

<meta name="Keywords"
  tal:attributes="content view/metadata/silva-extra/keywords"
/>

If you make your own view class for public display of a content object, you'll likely want to subclass it from SilvaLayout.browser.silvaviews.SilvaView to get this functionality too.

Views can reuse other views -- this way you can reuse common bits, such as a header or navigation elements, inside multiple templates without having to repeat yourself. You access them the following way:

context/@@browsertitle

The @@ notation indicates to Zope to only look for views called browsertitle (such as registered with name in browser:page), not a content object in Silva that happens to be called that way by an author. We recommend the use of @@ when reusing a view to avoid such name clashes.

Accessing resources, such as CSS files, images, and so on, happen through URLs. All resources are prefixed using ++resource++, thus this refers to some resource (an image named 'foo.jpg'):

path/to/site/++resource++foo.jpg

Resources can also be specified as groups, using all files directory, such as with the resourceDirectory directive described above. Individual resources are then below the name given to this resourceDirectory:

path/to/site/++resource++images/bar.jpg

It's important that a resource such as an image is accessed only through a single URL from all pages in a site, so that a browser can cache it. We currently have a rather complicated way to do this, which should be improved in the future.

In the request object SilvaLayout places a resourcebase object, which can be used to retrieve the base URL of root of the site under which the resources are available. For convenience you can use tal:define somewhere in your template so you can later easily get to it:

tal:define="resourcebase request/resourcebase/absolute_url"

Later on, you can then use resourcebase variable to refer to actual resources:

<link rel="stylesheet" tal:attributes="href
  string:${resourcebase}/++resource++styles/tree.css"/>

Some useful interfaces

An interface is not more than a design contract, or a description of an API - it specifies which methods and attributes a class implementing the interface should have. Interfaces are identified into ZCML using dotted names. Silva defines a number of useful interfaces you can connect views to using the browser:page directive:

  • silva.core.interfaces.ISilvaObject - all Silva objects provide this interface. If you want to connect your view to any Silva object, use this in the for attribute of a browser:page directive.
  • silva.core.interfaces.IContainer - all Silva containers, such as Folders, Publications and the Silva Root provide this interface.
  • silva.core.interfaces.IFolder - Silva Folders (but not publications) provide this interface.
  • silva.core.interfaces.IPublication - Silva Publications (but not Silva Folders) provide this interface. Silva Root is also considered to be a publication.
  • silva.core.interfaces.IRoot - Only the Silva Root provide this interface.
  • silva.core.interfaces.IVersionedContent - Only content objects that can have multiple versions, such as Silva Documents or Ghosts, provide this interface.
  • silva.core.interfaces.IGhost - only ghosts provide this interface.

More interfaces exist and each interface exposes an API that can be used through context.

Creating and overriding view classes

The view classes supplied by the SilvaLayout already provide means to implement filtering and easy access to metadata from page templates. Overriding view behaviour or adding new view classes is a little more involved. Acquiring familiarity with Python, Zope 3 interfaces and adapters is recommended.

SilvaLayout

2.2b1 (2010-01-25)

  • Make the SilvaLegacy skin error proof when there is no skin defined in ZMI.
  • Fix errors when a inexisting skin is selected (like the skin have been removed from the installation but still mark as used in Silva).
  • SilvaDefault is not registered by default.
  • Silva namespaces used in SilvaLayout have been updated.
  • Remove unused old AutoToc view.
  • Fix applySkin to handle correctly skin inheritence.
  • Use silva.core.interfaces instead of Products.Silva.interfaces.

2.2a2 (2009-01-12)

Bug fixes

  • Fix silvalegacy so overrides.html still works.
  • Remove broken tests.

2.2a1 (2008-11-17)

Features Added

  • Preview have been refactored to use a traverser and a namespace. Everything is handled automatically for the developer, no special action are required anymore.
  • Breadcrumbs have been fixed to work independently of the Virtual Host. The need for a metadata set to indicate that a Publication is a Virtual Host root is not need anymore and have been take away.
  • ConfigObject have been removed.
  • The product have been converted to use Grok. Lot of configuration code have been refactored.

Bug fixes

  • Only apply a skin on a container when it's different from the parent one.
  • Default layer should inherit from IDefaultBrowserLayer, otherwise you may not be able to override an already existing layout object (view, resource, ...).

1.4

Features Added

  • New Preview Method

    This new method removes the requirement that an explicit preview view for IContainer and IContent be defined for each layout. There is now a single 'preview_html' view defined for the SilvaDefault layout, for IContainer and IContent. These views simply call the current skin's index.html view. Before this happens, a parameter is added to the request, 'silva_view_mode=preview'.

    The public view of each layout is now also responsible for rendering the preview view. Typically this will just be rendering the editable content and editable title, since as of Silva 2.1 the publish buttons will be removed from the preview view interface.

    The base silvaview.SilvaView vase view class (available from the public view's template as the 'view' variable) has a new method, 'is_preview_view' and should be called by layouts to determine whether the current view is 'preview' or 'published'.

    Note that this method of using a request variable, 'silva_view_mode', is extensible to other views as well. The variable name is generic enough that you could have multiple custom views on an object which callback to the index.html template.

  • Added a configobject. This can be used instead of custom metadata sets to provide inheritable settings for specific SilvaLayout based layouts. See README.txt for an example of how to use this.

  • Added a new layout: SilvaLegacy. This layout can be used to support traditional, pre-SilvaLayout zodb-based layouts. i.e. using <silva_root>/(index_html|preview_html|content.html| layout_macro.html|override.html)

Bug fixes

  • Don't use a vocabulary to list availables skins, but list interfaces instead. This make SilvaLayout work with Zope 2.11.

1.3

Features Added

  • Added getPublicationMetadata method to get metadata directly from the containing publication.

1.2

Features Added

  • Added a metadata method to Silva View. metadata(set, field) will return the value of the relevant field for the current context.
  • Added html comments to the silva defaul layout so people will know when SilvaLayout is used rather than the normal layout in Silva.

1.1

Bugs fixed

  • 128518 Import of nonexisting skin gives a formulator SelectionValidator error.

Ported from 1.0 (Silva-1.6) branch

Features Added

Ported from 1.0 (Silva-1.6) branch

  • Added a subscriptor view to have subscription support with SilvaLayout.

1.0

Bugs fixed

  • Fixed bug in public preview where publish button was submitting to the wrong place.
  • Do not use redirect to status screen, just return to the public preview
  • Do not create a copy if the doc is already published

0.5.9

Features Added

  • Updated (crossported?) SilvaLayout publisher with improvements from core
  • Added a way to override the skin as set in the metadata from the request, in order to be able to have skins be triggered on user actions.
  • Added css class "selected" on the anchor in the tree that is the currently selected node.

0.5.7

  • Removed search template from Silva search so it can use the new Silva Find code from silva1.6

0.5.6

Bugs fixed

  • ChildNodes of non-container would raise StopIteration. This doesn't seem to work for iterators, so replaced this just returning an empty list.

0.5.5

Features Added

  • SilvaView now has a modificationtime method, which gets the modificationtime from the metadata of the content, or from the metadata of the default document of the container if the context is a container

0.5

  • Initial public release. (we were using internal release numbers before)

Download

Filename Release date Size
Products.SilvaLayout-2.2b1.tar.gz 25 jan 2010 15:15 30.0 k

Contact

FMI contact Infrae : info at infrae.com.