changeset 526:3f375a048402

moved search and dict into separate layers. removed search_template. added tocMode=concordance. fixed bug with paging tocs.
author casties
date Tue, 10 Apr 2012 19:41:44 +0200
parents 70c3ae5eac7c
children 652cc8d3f1a9
files css/docuviewer.css documentViewer.py zpt/changeDocumentViewer.zpt zpt/common_template.zpt zpt/layer_text_annotator.zpt zpt/layer_text_dict.zpt zpt/layer_text_gis.zpt zpt/layer_text_search.zpt zpt/search_template.zpt zpt/toc_concordance.zpt zpt/toc_figures.zpt zpt/toc_none.zpt zpt/toc_text.zpt zpt/toc_thumbs.zpt zpt/viewer_text.zpt
diffstat 15 files changed, 290 insertions(+), 182 deletions(-) [+]
line wrap: on
line diff
--- a/css/docuviewer.css	Thu Apr 05 19:29:50 2012 +0200
+++ b/css/docuviewer.css	Tue Apr 10 19:41:44 2012 +0200
@@ -17,12 +17,14 @@
 }
 
 div.toc-text .toc, 
-div.toc-figures .toc {
+div.toc-figures .toc,
+div.toc-concordance .toc {
     float:left;
     clear:right; 
 }
 div.toc-text .toc.float.right, 
-div.toc-figures .toc.float.right  {
+div.toc-figures .toc.float.right,
+div.toc-concordance .toc.float.right {
     float:right;
 }
 
--- a/documentViewer.py	Thu Apr 05 19:29:50 2012 +0200
+++ b/documentViewer.py	Tue Apr 10 19:41:44 2012 +0200
@@ -16,6 +16,7 @@
 import urlparse 
 import re
 import string
+import json
 
 from SrvTxtUtils import getInt, utf8ify, getText, getHttpData, refreshingImageFileIndexHtml
     
@@ -123,19 +124,22 @@
     viewer_images = PageTemplateFile('zpt/viewer_images', globals())
     viewer_index = PageTemplateFile('zpt/viewer_index', globals())
     # available layer types
-    availableLayers = {'text': ['dict','search','gis','annotator'],
-                       'xml': None, 'images': None, 'index': None}
+    builtinLayers = {'text': ['dict','search','gis','annotator'],
+                     'xml': None, 'images': None, 'index': None}
+    availableLayers = builtinLayers;
     # layer templates
+    layer_text_dict = PageTemplateFile('zpt/layer_text_dict', globals())
+    layer_text_search = PageTemplateFile('zpt/layer_text_search', globals())
     layer_text_annotator = PageTemplateFile('zpt/layer_text_annotator', globals())
     layer_text_gis = PageTemplateFile('zpt/layer_text_gis', globals())
     # toc templates
     toc_thumbs = PageTemplateFile('zpt/toc_thumbs', globals())
     toc_text = PageTemplateFile('zpt/toc_text', globals())
     toc_figures = PageTemplateFile('zpt/toc_figures', globals())
+    toc_concordance = PageTemplateFile('zpt/toc_concordance', globals())
     toc_none = PageTemplateFile('zpt/toc_none', globals())
     # other templates
     common_template = PageTemplateFile('zpt/common_template', globals())
-    search_template = PageTemplateFile('zpt/search_template', globals())
     info_xml = PageTemplateFile('zpt/info_xml', globals())
     docuviewer_css = ImageFile('css/docuviewer.css',globals())
     # make ImageFile better for development
@@ -408,6 +412,45 @@
         """link to documentviewer with parameter param set to val"""
         return self.getLink(param=param, val=val, params=params, baseUrl=baseUrl, paramSep='&', duplicates=duplicates)
     
+
+    def setAvailableLayers(self, newLayerString=None):
+        """sets availableLayers to newLayerString or tries to autodetect available layers.
+        assumes layer templates have the form layer_{m}_{l} for layer l in mode m.
+        newLayerString is parsed as JSON."""
+        if newLayerString is not None:
+            try:
+                layers = json.loads(newLayerString)
+                if 'text' in layers and 'images' in layers:
+                    self.availableLayers = layers
+                    return
+            except:
+                pass
+
+            logging.error("invalid layers=%s! autodetecting..."%repr(newLayerString))
+            
+        # start with builtin layers
+        self.availableLayers = self.builtinLayers.copy()
+        # add layers from templates
+        for t in self.template:
+            if t.startswith('layer_'):
+                try:
+                    (x, m, l) = t.split('_', 3)
+                    if m not in self.availableLayers:
+                        # mode m doesn't exist -> new list
+                        self.availableLayers[m] = [l]
+                        
+                    else:
+                        # m exists -> append
+                        if l not in self.availableLayers[m]:
+                            self.availableLayers[m].append()
+                            
+                except:
+                    pass
+
+    def getAvailableLayersJson(self):
+        """returns available layers as JSON string."""
+        return json.dumps(self.availableLayers)
+    
     
     def getInfo_xml(self,url,mode):
         """returns info about the document as XML"""
@@ -837,7 +880,7 @@
         else:
             batch['prevStart'] = None
             
-        if start + grpsize < maxIdx:
+        if start + grpsize <= maxIdx:
             batch['nextStart'] = start + grpsize
         else:
             batch['nextStart'] = None
@@ -863,12 +906,12 @@
         # list of elements in this batch
         this = []
         j = 0
-        for i in range(start, min(start+size, end)):
+        for i in range(start, min(start+size, end+1)):
             if data:
                 if fullData:
-                    d = data[i]
+                    d = data.get(i, None)
                 else:
-                    d = data[j]
+                    d = data.get(j, None)
                     j += 1
             
             else:
@@ -887,13 +930,14 @@
         else:
             batch['nextStart'] = None
         
+        logging.debug("getBatch start=%s size=%s end=%s batch=%s"%(start,size,end,repr(batch)))
         return batch
         
 
     security.declareProtected('View management screens','changeDocumentViewerForm')    
     changeDocumentViewerForm = PageTemplateFile('zpt/changeDocumentViewer', globals())
     
-    def changeDocumentViewer(self,title="",digilibBaseUrl=None,thumbrows=2,thumbcols=5,authgroups='mpiwg',RESPONSE=None):
+    def changeDocumentViewer(self,title="",digilibBaseUrl=None,thumbrows=2,thumbcols=5,authgroups='mpiwg',availableLayers=None,RESPONSE=None):
         """init document viewer"""
         self.title=title
         self.digilibBaseUrl = digilibBaseUrl
@@ -905,6 +949,8 @@
             self.metadataService = getattr(self, 'metadata')
         except Exception, e:
             logging.error("Unable to find MetaDataFolder 'metadata': "+str(e))
+            
+        self.setAvailableLayers(availableLayers)
 
         if RESPONSE is not None:
             RESPONSE.redirect('manage_main')
--- a/zpt/changeDocumentViewer.zpt	Thu Apr 05 19:29:50 2012 +0200
+++ b/zpt/changeDocumentViewer.zpt	Tue Apr 10 19:41:44 2012 +0200
@@ -17,6 +17,10 @@
         <p class="form-element"><input size="80" tal:attributes="value python:','.join(getattr(here,'authgroups', []))" name="authgroups"></p>
         <p class="form-text">Access groups (separated by ',') that are considered local, i.e. when a ressource restricts access
         to one of these groups, local access to the ressource is granted.</p>
+        <p class="form-optional">Available Layers</p>
+        <p class="form-element"><input size="80" tal:attributes="value here/getAvailableLayersJson | nothing" name="availableLayers"></p>
+        <p class="form-text">List of available layers per view mode. JSON, one key per mode, null, or a list of layers per key.
+          Leave empty for autoconfiguration.</p>
         <p class="form-optional">Digilib base URL</p>
         <p class="form-element"><input size="80" tal:attributes="value here/digilibBaseUrl | nothing" name="digilibBaseUrl"></p>
         <p class="form-text">Leave empty for autoconfiguration.</p>
--- a/zpt/common_template.zpt	Thu Apr 05 19:29:50 2012 +0200
+++ b/zpt/common_template.zpt	Tue Apr 10 19:41:44 2012 +0200
@@ -66,5 +66,31 @@
     </form>
   </metal:block>
 
+  <!-- toc type switcher -->
+  <metal:block metal:define-macro="toc_switcher">
+    <ul class="switcher">
+      <li tal:attributes="class python:test(tocMode=='thumbs', 'sel', None)"><a
+        tal:attributes="href python:here.getLink('tocMode','thumbs')">Thumbnails</a>
+      </li>
+      <li tal:attributes="class python:test(tocMode=='text', 'sel', None)"
+        tal:condition="python:docpath and docinfo.get('numTocEntries', None)">
+        <a tal:attributes="href python:here.getLink('tocMode','text')">Content</a>
+      </li>
+      <li tal:attributes="class python:test(tocMode=='figures', 'sel', None)"
+        tal:condition="python:docpath and docinfo.get('numFigureEntries', None)">
+        <a
+        tal:attributes="href python:here.getLink('tocMode','figures')">Figures</a>
+      </li>
+      <li tal:attributes="class python:test(tocMode=='concordance', 'sel', None)"
+        tal:condition="python:docpath and docinfo.get('pageNumbers', None)">
+        <a
+        tal:attributes="href python:here.getLink('tocMode','concordance')">Concordance</a>
+      </li>
+      <li tal:attributes="class python:test(tocMode=='none', 'sel', None)"><a
+        tal:attributes="href python:here.getLink('tocMode','none')">None</a>
+      </li>
+    </ul>
+  </metal:block>
+
 </body>
 </html>
--- a/zpt/layer_text_annotator.zpt	Thu Apr 05 19:29:50 2012 +0200
+++ b/zpt/layer_text_annotator.zpt	Tue Apr 10 19:41:44 2012 +0200
@@ -2,7 +2,7 @@
           "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-<metal:block metal:define-macro="html_head">
+<metal:block metal:define-macro="html_head" tal:condition="python:'annotator' in viewLayers">
   <!--  annotator -->
   <link rel="stylesheet" type="text/css"
     tal:attributes="href string:$rootUrl/template/annotator_files/css/annotator.css" />
@@ -87,7 +87,7 @@
     </ul>
   </div>
 
-  <metal:block metal:define-macro="options_box">
+  <metal:block metal:define-macro="options_box" tal:condition="python:'annotator' in viewLayers">
     <!-- BEGIN ANNOTATIONS -->
     <div class="options">
       <h4>Annotations</h4>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/zpt/layer_text_dict.zpt	Tue Apr 10 19:41:44 2012 +0200
@@ -0,0 +1,44 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<!-- not used here
+<metal:block metal:define-macro="html_head">
+</metal:block>
+-->
+</head>
+<body>
+  <!-- right-side options -->
+  <div class="col buttons">
+    <!-- LAYER DISPLAY OPTION  -->
+    <ul>
+      <metal:block metal:define-macro="layer_select_li">
+        <li>
+          <input type="checkbox" class="autosubmit" name="viewLayer" value="dict"
+            tal:attributes="checked python:'dict' in viewLayers" /> Dictionary
+        </li>
+      </metal:block>
+    </ul>
+  </div>
+
+  <metal:block metal:define-macro="options_box" tal:condition="python:'dict' in viewLayers">
+    <!--"BEGIN DICTIONARY OVERVIEW"-->
+    <div class="options">
+      <h4>Dictionary view</h4>
+      <form name="f3" action="">
+        <ul>
+          <li>
+            <input type="radio" name="r3" /> Tab
+          </li>
+          <li>
+            <input type="radio" name="r3" /> Window
+          </li>
+        </ul>
+      </form>
+    </div>
+    <!--"END DICTIONARY OVERVIEW"-->
+  </metal:block>
+
+</body>
+
+</html>
--- a/zpt/layer_text_gis.zpt	Thu Apr 05 19:29:50 2012 +0200
+++ b/zpt/layer_text_gis.zpt	Tue Apr 10 19:41:44 2012 +0200
@@ -21,9 +21,9 @@
     </ul>
   </div>
 
-  <metal:block metal:define-macro="options_box">
+  <metal:block metal:define-macro="options_box" tal:condition="python:'gis' in viewLayers">
     <!--"BEGIN PLACES"-->
-    <div class="options" tal:condition="python:'gis' in viewLayers">
+    <div class="options">
       <tal:block
         tal:define="
             name docinfo/documentName;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/zpt/layer_text_search.zpt	Tue Apr 10 19:41:44 2012 +0200
@@ -0,0 +1,90 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<metal:block metal:define-macro="html_head"
+  tal:define="
+    global query python:request.get('query', None); 
+    global queryType python:request.get('queryType','fulltextMorph');
+">
+</metal:block>
+</head>
+<body>
+  <!-- right-side options -->
+  <div class="col buttons">
+    <!-- LAYER DISPLAY OPTION  -->
+    <ul>
+      <metal:block metal:define-macro="layer_select_li">
+        <li tal:condition="python:query">
+          <input type="checkbox" class="autosubmit" name="viewLayer" value="search"
+            tal:attributes="checked python:'search' in viewLayers" /> Search hits
+        </li>
+      </metal:block>
+    </ul>
+  </div>
+
+  <metal:block metal:define-macro="extra_column" tal:condition="python:'search' in viewLayers">
+    <!-- right-side search results -->
+    <div class="col results" tal:condition="query">
+      <!--"BEGIN SEARCH RESULTS"  -->
+      <div class="options">
+        <h4>Search results</h4>
+        <div
+          tal:define="start pageinfo/resultStart; resultsize python:docinfo.get('resultSize',0); grpsize pageinfo/resultPageSize;
+                batch python:here.getBatch(start=start,size=grpsize,end=resultsize);">
+          <div class="ruler" tal:define="startParam string:resultStart">
+            <metal:block metal:use-macro="here/template/common_template/macros/toc_ruler" />
+          </div>
+          <div class="content"
+            tal:content="structure python:here.getResultsPage(mode=queryType,query=query,start=start,size=grpsize,pageinfo=pageinfo,docinfo=docinfo)" />
+        </div>
+      </div>
+    </div>
+  </metal:block>
+
+  <metal:block metal:define-macro="options_box">
+    <!--"BEGIN SEARCH"-->
+    <div class="options">
+      <h4>Search</h4>
+      <form tal:attributes="action viewerUrl">
+        <input type="hidden"
+          tal:define="params python:here.getParams(params={'query':None,'queryType':None,'viewLayer':None})"
+          tal:repeat="param params"
+          tal:attributes="name param; value python:params[param]" />
+        <!-- make sure we have one viewLayer=search -->
+        <tal:block tal:repeat="vl viewLayers">
+          <input type="hidden" name="viewLayer" tal:attributes="value vl"
+            tal:condition="python:vl != 'search'" />
+        </tal:block>
+        <input type="hidden" name="viewLayer" value="search" />
+        <!-- query text -->
+        <input type="text" name="query" tal:attributes="value query" /> <input
+          type="submit" value="Search" /> <a
+          tal:attributes="href python:here.getLink('query',None)">Clear</a>
+        <ul>
+          <li>
+            <input type="radio" name="queryType" value="fulltext"
+              tal:attributes="checked python:queryType=='fulltext'" /> Exact
+          </li>
+          <li>
+            <input type="radio" name="queryType" value="fulltextMorph"
+              tal:attributes="checked python:queryType=='fulltextMorph'" /> All forms
+          </li>
+          <li>
+            <input type="radio" name="queryType" value="ftIndex"
+              tal:attributes="checked python:queryType=='ftIndex'" /> Fulltext index
+          </li>
+          <li>
+            <input type="radio" name="queryType" value="ftIndexMorph"
+              tal:attributes="checked python:queryType=='ftIndexMorph'" /> Morphological
+            index
+          </li>
+        </ul>
+      </form>
+    </div>
+    <!--"END SEARCH"-->
+  </metal:block>
+
+</body>
+
+</html>
--- a/zpt/search_template.zpt	Thu Apr 05 19:29:50 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-</head>
-<body>
-  <!-- block used for main content area -->
-  <div metal:define-macro="results_div"
-    tal:define="start pageinfo/resultStart; resultsize python:docinfo.get('resultSize',0); grpsize pageinfo/resultPageSize;
-                batch python:here.getBatch(start=start,size=grpsize,end=resultsize);">
-    <div class="ruler" tal:define="startParam string:resultStart">
-        <metal:block metal:use-macro="here/template/common_template/macros/toc_ruler"/>
-    </div>
-    <div class="content"
-      tal:content="structure python:here.getResultsPage(mode=queryType,query=query,start=start,size=grpsize,pageinfo=pageinfo,docinfo=docinfo)" />
-  </div>
-<!--  tal:content="structure python:here.getResultsPage(mode=queryType,query=query,pn=1,pageinfo=pageinfo,docinfo=docinfo)" -->
-<!--  structure python:here.getTocPage(mode='text',start=start,pageinfo=pageinfo,docinfo=docinfo) -->
-</body>
-</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/zpt/toc_concordance.zpt	Tue Apr 10 19:41:44 2012 +0200
@@ -0,0 +1,47 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+</head>
+<body>
+  <!-- block used for main content area -->
+  <div class="toc-concordance" metal:define-macro="main"
+    tal:define="start pageinfo/start; tocsize docinfo/numPages; grpsize pageinfo/tocPageSize;
+                pageNumbers docinfo/pageNumbers | nothing;
+                batch python:here.getBatch(start=start,size=grpsize,end=tocsize,data=pageNumbers);">
+    <div metal:use-macro="here/template/common_template/macros/toc_switcher" />
+    <div class="ruler">
+      <metal:block metal:use-macro="here/template/common_template/macros/toc_ruler" />
+    </div>
+    <div class="content">
+      <table tal:condition="pageNumbers">
+        <tr>
+          <th>Scan</th>
+          <th>Original</th>
+        </tr>
+        <tr tal:repeat="toc batch/this">
+          <tal:block tal:define="pn toc/pn | nothing">
+            <td>
+              <a tal:condition="pn"
+                tal:attributes="href python:here.getLink('pn', toc['pn'])"
+                tal:content="toc/pn" title="Scan number">ScanNo</a>
+            </td>
+            <td>
+              <span class="originalPage" title="Original page number"
+                tal:define="originalPage toc/no | nothing"
+                tal:condition="python:originalPage!=None"><span
+                tal:replace="originalPage" /><span
+                tal:define="originalPageNorm toc/non | nothing"
+                tal:condition="python:originalPageNorm!=None"> [<span
+                  tal:replace="originalPageNorm" />]
+              </span></span>
+            </td>
+          </tal:block>
+        </tr>
+      </table>
+    </div>
+  </div>
+  <!-- /toc -->
+</body>
+</html>
--- a/zpt/toc_figures.zpt	Thu Apr 05 19:29:50 2012 +0200
+++ b/zpt/toc_figures.zpt	Tue Apr 10 19:41:44 2012 +0200
@@ -9,29 +9,13 @@
   <div class="toc-figures" metal:define-macro="main"
     tal:define="start pageinfo/start; tocsize docinfo/numFigureEntries; grpsize pageinfo/tocPageSize;
                 batch python:here.getBatch(start=start,size=grpsize,end=tocsize);">
-    <ul class="switcher">
-      <li><a
-        tal:attributes="href python:here.getLink('tocMode','thumbs')">Thumbnails</a>
-      </li>
-      <li
-        tal:condition="python:docpath and docinfo.get('numTocEntries', None)">
-        <a tal:attributes="href python:here.getLink('tocMode','text')">Content</a>
-      </li>
-      <li class="sel"
-        tal:condition="python:docpath and docinfo.get('numFigureEntries', None)">
-        <a
-        tal:attributes="href python:here.getLink('tocMode','figures')">Figures</a>
-      </li>
-      <li><a
-        tal:attributes="href python:here.getLink('tocMode','none')">None</a>
-      </li>
-    </ul>
+    <div metal:use-macro="here/template/common_template/macros/toc_switcher"/>
     <div class="ruler">
         <metal:block metal:use-macro="here/template/common_template/macros/toc_ruler"/>
     </div>
     <div class="content"
       tal:content="structure python:here.getTocPage(mode='figures',start=start,pageinfo=pageinfo,docinfo=docinfo)" />
   </div>
-  <!-- toc -->
+  <!-- /toc -->
 </body>
 </html>
--- a/zpt/toc_none.zpt	Thu Apr 05 19:29:50 2012 +0200
+++ b/zpt/toc_none.zpt	Tue Apr 10 19:41:44 2012 +0200
@@ -7,20 +7,7 @@
 <body>
   <!-- block used for main content area -->
   <div class="toc-none" metal:define-macro="main">
-    <ul class="switcher">
-      <li>
-        <a tal:attributes="href python:here.getLink('tocMode','thumbs')">Thumbnails</a>
-      </li>
-      <li tal:condition="python:docpath and docinfo.get('numTocEntries', None)">
-        <a tal:attributes="href python:here.getLink('tocMode','text')">Content</a>
-      </li>
-      <li tal:condition="python:docpath and docinfo.get('numFigureEntries', None)">
-        <a tal:attributes="href python:here.getLink('tocMode','figures')">Figures</a>
-      </li>
-      <li class="sel">
-        <a tal:attributes="href python:here.getLink('tocMode','none')">None</a>
-      </li>
-    </ul>
+    <div metal:use-macro="here/template/common_template/macros/toc_switcher"/>
     <div class="content"></div>
   </div>
   <!-- toc -->
--- a/zpt/toc_text.zpt	Thu Apr 05 19:29:50 2012 +0200
+++ b/zpt/toc_text.zpt	Tue Apr 10 19:41:44 2012 +0200
@@ -9,23 +9,7 @@
   <div class="toc-text" metal:define-macro="main"
     tal:define="start pageinfo/start; tocsize docinfo/numTocEntries; grpsize pageinfo/tocPageSize;
                 batch python:here.getBatch(start=start,size=grpsize,end=tocsize);">
-    <ul class="switcher">
-      <li><a
-        tal:attributes="href python:here.getLink('tocMode','thumbs')">Thumbnails</a>
-      </li>
-      <li class="sel"
-        tal:condition="python:docpath and docinfo.get('numTocEntries', None)">
-        <a tal:attributes="href python:here.getLink('tocMode','text')">Content</a>
-      </li>
-      <li
-        tal:condition="python:docpath and docinfo.get('numFigureEntries', None)">
-        <a
-        tal:attributes="href python:here.getLink('tocMode','figures')">Figures</a>
-      </li>
-      <li><a
-        tal:attributes="href python:here.getLink('tocMode','none')">None</a>
-      </li>
-    </ul>
+    <div metal:use-macro="here/template/common_template/macros/toc_switcher"/>
     <div class="ruler">
         <metal:block metal:use-macro="here/template/common_template/macros/toc_ruler"/>
     </div>
--- a/zpt/toc_thumbs.zpt	Thu Apr 05 19:29:50 2012 +0200
+++ b/zpt/toc_thumbs.zpt	Tue Apr 10 19:41:44 2012 +0200
@@ -14,20 +14,7 @@
                 pageNumbers docinfo/pageNumbers | nothing;
                 left python:test(flowLtr,pageBatch['prevStart'],pageBatch['nextStart']);
                 right python:test(flowLtr,pageBatch['nextStart'],pageBatch['prevStart']);">
-    <ul class="toctype">
-      <li class="sel">
-        <a tal:attributes="href python:here.getLink('tocMode','thumbs')">Thumbnails</a>
-      </li>
-      <li tal:condition="python:docinfo.get('numTocEntries', None)">
-        <a tal:attributes="href python:here.getLink('tocMode','text')">Content</a>
-      </li>
-      <li tal:condition="python:docinfo.get('numFigureEntries', None)">
-        <a tal:attributes="href python:here.getLink('tocMode','figures')">Figures</a>
-      </li>
-      <li>
-        <a tal:attributes="href python:here.getLink('tocMode','none')">None</a>
-      </li>
-    </ul>
+    <div metal:use-macro="here/template/common_template/macros/toc_switcher"/>
 
     <div class="content">
       <div class="ruler">
--- a/zpt/viewer_text.zpt	Thu Apr 05 19:29:50 2012 +0200
+++ b/zpt/viewer_text.zpt	Tue Apr 10 19:41:44 2012 +0200
@@ -23,8 +23,8 @@
     });
 // -->
 </script>
-<!--  layer headers -->
-<tal:block tal:repeat="layer viewLayers">
+<!--  layer headers (rendered always) -->
+<tal:block tal:repeat="layer availableLayers">
   <tal:block tal:define="mpath string:here/template/layer_text_${layer}/macros/html_head"
     tal:condition="python:exists(mpath)">
     <metal:block metal:use-macro="python:path(mpath)" />
@@ -37,8 +37,6 @@
     tal:define="docpath docinfo/textURLPath;
                 pn pageinfo/pn; 
                 flowLtr python:docinfo.get('pageFlow','ltr')!='rtl';
-                query python:request.get('query', None); 
-                queryType python:request.get('queryType','fulltextMorph');
                 textPage python:here.getTextPage(mode=viewLayer, pn=pn, docinfo=docinfo, pageinfo=pageinfo) or '[no text here]';">
     <!-- header -->
     <div class="page-head">
@@ -70,14 +68,13 @@
       </div>
       <!-- end of col-main -->
 
-      <!-- right-side search results -->
-      <div class="col results" tal:condition="query">
-        <!--"BEGIN SEARCH RESULTS"  -->
-        <div class="options">
-          <h4>Search results</h4>
-          <div metal:use-macro="here/template/search_template/macros/results_div" />
-        </div>
-      </div>
+      <!--  layer columns (rendered always) -->
+      <tal:block tal:repeat="layer availableLayers">
+        <tal:block tal:define="mpath string:here/template/layer_text_${layer}/macros/extra_column"
+          tal:condition="python:exists(mpath)">
+          <metal:block metal:use-macro="python:path(mpath)" />
+        </tal:block>
+      </tal:block>
 
       <!-- right-side options -->
       <div class="col buttons">
@@ -94,19 +91,7 @@
                 <input class="autosubmit" type="radio" name="viewMode" value="text"
                   tal:attributes="checked python:viewMode=='text'" /> Text
                 <ul>
-                  <!-- text layers -->
-                  <li>
-                    <input type="checkbox" class="autosubmit" name="viewLayer"
-                      value="dict" tal:attributes="checked python:'dict' in viewLayers" />
-                    Dictionary
-                  </li>
-                  <li tal:condition="python:query">
-                    <input type="checkbox" class="autosubmit" name="viewLayer"
-                      value="search"
-                      tal:attributes="checked python:'search' in viewLayers" /> Search
-                    hits
-                  </li>
-                  <!-- auto-layer select buttons -->
+                  <!-- text layer select buttons (rendered always) -->
                   <tal:block tal:repeat="layer availableLayers">
                     <tal:block
                       tal:define="mpath string:here/template/layer_text_${layer}/macros/layer_select_li"
@@ -126,47 +111,6 @@
         </div>
         <!--"END TEXT DISPLAY"-->
 
-        <!--"BEGIN SEARCH"-->
-        <div class="options">
-          <h4>Search</h4>
-          <form tal:attributes="action viewerUrl">
-            <input type="hidden"
-              tal:define="params python:here.getParams(params={'query':None,'queryType':None,'viewLayer':None})"
-              tal:repeat="param params"
-              tal:attributes="name param; value python:params[param]" />
-            <!-- make sure we have one viewLayer=search -->
-            <tal:block tal:repeat="vl viewLayers">
-              <input type="hidden" name="viewLayer" tal:attributes="value vl"
-                tal:condition="python:vl != 'search'" />
-            </tal:block>
-            <input type="hidden" name="viewLayer" value="search" />
-            <!-- query text -->
-            <input type="text" name="query" tal:attributes="value query" /> <input
-              type="submit" value="Search" /> <a
-              tal:attributes="href python:here.getLink('query',None)">Clear</a>
-            <ul>
-              <li>
-                <input type="radio" name="queryType" value="fulltext"
-                  tal:attributes="checked python:queryType=='fulltext'" /> Exact
-              </li>
-              <li>
-                <input type="radio" name="queryType" value="fulltextMorph"
-                  tal:attributes="checked python:queryType=='fulltextMorph'" /> All forms
-              </li>
-              <li>
-                <input type="radio" name="queryType" value="ftIndex"
-                  tal:attributes="checked python:queryType=='ftIndex'" /> Fulltext index
-              </li>
-              <li>
-                <input type="radio" name="queryType" value="ftIndexMorph"
-                  tal:attributes="checked python:queryType=='ftIndexMorph'" />
-                Morphological index
-              </li>
-            </ul>
-          </form>
-        </div>
-        <!--"END SEARCH"-->
-
         <!--"BEGIN TEXT SIZE"-->
         <div class="options">
           <h4>Text size</h4>
@@ -184,22 +128,6 @@
         </div>
         <!--"END TEXT SIZE"-->
 
-        <!--"BEGIN DICTIONARY OVERVIEW"-->
-        <div class="options" tal:condition="python:'dict' in viewLayers">
-          <h4>Dictionary view</h4>
-          <form name="f3" action="">
-            <ul>
-              <li>
-                <input type="radio" name="r3" /> Tab
-              </li>
-              <li>
-                <input type="radio" name="r3" /> Window
-              </li>
-            </ul>
-          </form>
-        </div>
-        <!--"END DICTIONARY OVERVIEW"-->
-
         <!--"BEGIN TEXT NORMALIZATION"-->
         <div class="options">
           <h4>Text normalization</h4>
@@ -229,8 +157,8 @@
         </div>
         <!--"END TEXT NORMALIZATION"-->
 
-        <!--  auto-layer option boxes -->
-        <tal:block tal:repeat="layer viewLayers">
+        <!--  layer option boxes (rendered if active) -->
+        <tal:block tal:repeat="layer availableLayers">
           <tal:block
             tal:define="mpath string:here/template/layer_text_${layer}/macros/options_box"
             tal:condition="python:exists(mpath)">