[Zope] HOWTO (but to be improved) - linking to neighbours

Marcin Kasperski Marcin.Kasperski@softax.com.pl
Wed, 16 Aug 2000 12:46:00 +0200


[ Below I describe my solution to the problem which seems to me to be
fairly frequent. Maybe someone is interested, maybe someone can show me
better (faster, shorter) solution ]

* Problem 

The problem: while presenting some page, I would like to automagically
add links to 'previous' and 'next' page in the same directory. Say you
organize a bunch of HOWTOS and you would like to let the people navigate
via 'next' links - without going back go table of contents.

* Idea

What I really need is to calculate identifiers of 'neighbours' of my
page in its container. I do have id of the current page, I can easily
got list of all identifiers in the container. So I can just scan this
list, find my id and read previous and next element. Transforming it
into hyperlink is natural.

* Code

First I create the following Python Method (could be External Method as
well). The method returns tuple (previous_id, next_id) substituting ''
if there is no such element (we are at the start or at the end).

----------
Name: neighbours
Parameters: self,myId,allIds
Contents:

position = 0
for x in range(0, len(allIds)):
    if allIds[x] == myId:
        position = x
        break
else:
    raise 'Internal inconsistency: id ' + str(myId) + ' does not belong
to list ' + str(allIds)

left = ''
right = ''

if position > 0:
    left = allIds[position - 1]
if position < len(allIds) - 1:
    right = allIds[position + 1]

return (left, right)
----------

Then I add standard_html_footer DTML Method to the directory with my
iterated items. I put there sth like that (of course presentation can
vary, 'MyHowto' is the metatype of objects I iterate over, as you can
see I call original footer after writting my navigational details):

---------
<p>
<dtml-let allIds="PARENTS[0].objectIds(['MyHowto'])"
     myId=id
     neigh="neighbours(myId,allIds)">

  <table border="0" width="90%" align="center"><tr>
    <td width="33%" align="left">
       <dtml-if "neigh[0] != ''">
          <a href="<dtml-var "neigh[0]">">Previous</a>
       <dtml-else>
          &nbsp;
       </dtml-if>
    </td>
    <td width="33%" align="center">
       <a href="<dtml-var howto_index url>">Table of Contents</a>
    </td>
    <td width="33%" align="right">
       <dtml-if "neigh[1] != ''">
          <a href="<dtml-var "neigh[1]">">Next</a>
       <dtml-else>
          &nbsp;
       </dtml-if>
    </td>
  </tr></table>

</dtml-let>

<dtml-with "PARENTS[1]">
<dtml-var standard_html_footer>
</dtml-with>

----------

(by the way I do not know why I need 'myId=id' in <let> - but removing
it and putting id on the neighbours parameters list does not work)

* Unsolved problems

There are two important unsolved problems:
- efficiency - I perform linear scan which can be expensive if my
directory contains a lot of objects (I do not know good method to solve
it - I would need some help from Folder class)
- order - if I need to present my objects in some order other than
default, I would need to sort allIds in some way (probably I would need
youse objectValues instead of objectIds)

* Minor tricks

The python method I wrote is generic, I use the same method for two
different folders.

In fact I worked around the order problem for the very simple case -
presenting everything in reverse order. I just exchanged neigh[0] and
neigh[1] in standard_html_footer.



-- Serwis nie tylko mieszkaniowy: http://www.mk.w.pl 
|
| You have the right to say how long each requirement will take you to  
| implement, and to revise estimates given experience. (Ken Beck's      
| Second Developer Right)