From d74aace9ed8079a5a2430f3c0cc56ff39934279b Mon Sep 17 00:00:00 2001
From: chris <chris@teacherscpd.co.uk>
Date: Thu, 28 Jul 2005 02:55:22 +0200
Subject: [PATCH] footnote fix: almagamate identical footnotes, insitu footnote
 popups

darcs-hash:20050728005522-50fdc-f359021d5bcf602c2c403d37852196d5eeb4d473.gz
---
 inc/parser/xhtml.php       | 59 ++++++++++++++++++++++++++++++--------
 inc/template.php           |  6 ++++
 lib/scripts/script.js      | 44 ++++++++++++++++++++++++++++
 lib/tpl/default/design.css |  9 ++++++
 4 files changed, 106 insertions(+), 12 deletions(-)

diff --git a/inc/parser/xhtml.php b/inc/parser/xhtml.php
index 81f0b2dca..2fd5844d0 100644
--- a/inc/parser/xhtml.php
+++ b/inc/parser/xhtml.php
@@ -51,8 +51,34 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
         
         if ( count ($this->footnotes) > 0 ) {
             $this->doc .= '<div class="footnotes">'.DOKU_LF;
+
+            $id = 0;
             foreach ( $this->footnotes as $footnote ) {
-                $this->doc .= $footnote;
+                $id++;   // the number of the current footnote
+                
+                // check its not a placeholder that indicates actual footnote text is elsewhere
+                if (substr($footnote, 0, 5) != "@@FNT") {
+
+                    // open the footnote and set the anchor and backlink
+                    $this->doc .= '<div class="fn">';
+                    $this->doc .= '<a href="#fnt'.$id.'" id="fn'.$id.'" name="fn'.$id.'" class="fn_bot">';
+                    $this->doc .= $id.')</a> '.DOKU_LF;
+                    
+                    // get any other footnotes that use the same markup
+                    $alt = array_keys($this->footnotes, "@@FNT$id");
+                    
+                    if (count($alt)) {
+                      foreach ($alt as $ref) {
+                        // set anchor and backlink for the other footnotes
+                        $this->doc .= ', <a href="#fnt'.($ref+1).'" id="fn'.($ref+1).'" name="fn'.($ref+1).'" class="fn_bot">';
+                        $this->doc .= ($ref+1).')</a> '.DOKU_LF;                  
+                      }
+                    }
+                    
+                    // add footnote markup and close this footnote
+                    $this->doc .= $footnote;
+                    $this->doc .= '</div>' . DOKU_LF;
+                }
             }
             $this->doc .= '</div>'.DOKU_LF;
         }
@@ -209,23 +235,16 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
      * Callback for footnote start syntax
      *
      * All following content will go to the footnote instead of
-     * the document. To achive this the previous rendered content
+     * the document. To achieve this the previous rendered content
      * is moved to $store and $doc is cleared
      *
      * @author Andreas Gohr <andi@splitbrain.org>
      */
     function footnote_open() {
-        #$id = $this->_newFootnoteId();
-        $id = count($this->footnotes)+1;
-        $this->doc .= '<a href="#fn'.$id.'" name="fnt'.$id.'" class="fn_top">'.$id.')</a>';
 
         // move current content to store and record footnote
         $this->store = $this->doc;
         $this->doc   = '';
-
-        $this->doc .= '<div class="fn">';
-        $this->doc .= '<a href="#fnt'.$id.'" name="fn'.$id.'" class="fn_bot">';
-        $this->doc .= $id.')</a> '.DOKU_LF;
     }
     
     /**
@@ -237,12 +256,28 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
      * @author Andreas Gohr
      */
     function footnote_close() {
-        $this->doc .= '</div>' . DOKU_LF;
 
-        // put recorded footnote into the stack and restore old content
-        $this->footnotes[count($this->footnotes)] = $this->doc;
+        // recover footnote into the stack and restore old content
+        $footnote = $this->doc;
         $this->doc = $this->store;
         $this->store = '';
+        
+        // check to see if this footnote has been seen before
+        $i = array_search($footnote, $this->footnotes);
+        
+        if ($i === false) {
+            // its a new footnote, add it to the $footnotes array
+            $id = count($this->footnotes)+1;
+            $this->footnotes[count($this->footnotes)] = $footnote;
+        } else {
+            // seen this one before, translate the index to an id and save a placeholder
+            $i++;
+            $id = count($this->footnotes)+1;
+            $this->footnotes[count($this->footnotes)] = "@@FNT".($i);
+        }
+
+        // output the footnote reference and link, incl. onmouseover for insitu footnote popup
+        $this->doc .= '<a href="#fn'.$id.'" name="fnt'.$id.'" class="fn_top" onmouseover="fnt(\''.$id.'\', this, event);">'.$id.')</a>';
     }
     
     function listu_open() {
diff --git a/inc/template.php b/inc/template.php
index 90fbe5a32..ac5ea3d67 100644
--- a/inc/template.php
+++ b/inc/template.php
@@ -185,6 +185,12 @@ function tpl_metaheaders(){
     ptln('<script language="javascript" type="text/javascript" charset="utf-8" src="'.
        DOKU_BASE.'lib/scripts/spellcheck.js"></script>',$it);
   }
+  
+  // dom tool tip library, for insitu footnotes
+  ptln('<script language="javascript" type="text/javascript" charset="utf-8" src="'.
+       DOKU_BASE.'lib/scripts/domLib.js"></script>',$it);
+  ptln('<script language="javascript" type="text/javascript" charset="utf-8" src="'.
+       DOKU_BASE.'lib/scripts/domTT.js"></script>',$it);
 
   //FIXME include some default CSS ? IE FIX?
 }
diff --git a/lib/scripts/script.js b/lib/scripts/script.js
index 9d667c7af..58785dbde 100644
--- a/lib/scripts/script.js
+++ b/lib/scripts/script.js
@@ -457,3 +457,47 @@ function checkAclLevel(){
     }
   }
 }
+
+/* insitu footnote addition
+ * provide a wrapper for domTT javascript library
+ * this function is placed in the onmouseover event of footnote references in the main page
+ * 
+ * @author Chris Smith <chris [at] jalakai [dot] co [dot] uk>
+ */
+var currentFootnote = 0;
+function fnt(id, e, evt) {
+
+    if (currentFootnote && id != currentFootnote) {
+        domTT_close(document.getElementById('insitu-fn'+currentFootnote));
+    }
+    
+    // does the footnote tooltip already exist?
+    var fnt = document.getElementById('insitu-fn'+id);
+    if (!fnt) {
+        // if not create it...
+    
+        // locate the footnote anchor element
+        var a = document.getElementById( "fn"+id );    
+        if (!a) return;
+        
+        // anchor parent is the footnote container, get its innerHTML
+        var footnote = new String (a.parentNode.innerHTML);
+        
+        // strip the leading footnote anchors and their comma separators
+        footnote = footnote.replace(/<a\s*href=\".*\#fnt\d+\".*?<\/a>/gi, '');
+        footnote = footnote.replace(/^\s+(,\s+)+/,'');
+        
+        // prefix ids on any elements with "insitu-" to ensure they remain unique
+        footnote = footnote.replace(/\bid=\"(.*?)\"/gi,'id="insitu-$1');
+        
+        // create the DOM node, assign an id, a class and the footnote content
+        fnt = document.createElement("div");
+        fnt.id = "insitu-fn"+id;
+        fnt.className = "insitu-footnote";
+        fnt.innerHTML = footnote;
+    }
+    
+    // activate the tooltip
+    domTT_activate(e, evt, 'content', fnt, 'type', 'velcro');
+    currentFootnote = id;    
+}
diff --git a/lib/tpl/default/design.css b/lib/tpl/default/design.css
index 41a34dd5f..af7998317 100644
--- a/lib/tpl/default/design.css
+++ b/lib/tpl/default/design.css
@@ -568,6 +568,15 @@ a.fn_bot{
   font-weight:bold;
 }
 
+/* insitu-footnotes */
+div.insitu-footnote {
+  font-size: 80%;
+  line-height: 1.2em;
+  border: 1px solid #8cacbb;
+  background: #eef3f8;
+  text-align: left;
+  padding: 4px;
+}
 
 /* --------------- search result formating --------------- */
 .search_result{
-- 
GitLab