23

I work as a Physics teacher and I am writing a "Problem-Solution-Book" with hyperlinks from problems to solutions and backreferencing -- all of it works pretty good.

Now I wanted to introduce something like a "Hint" - text at the problem header which is used as a tooltip, indicating some hints for possible ways to the solution (apart from directly clicking the "solution" link ;-))

I wonder whether it is possible to use LaTeX code in the second argument of the \pdftooltip command from pdfcomment package by Josef Kleber. I am using pdflatex and pdfcomment version 2.3a.

What I want to do is:

Using the \pdftooltip command and as the mouse moves over the relevant portion a tooltip box with, say, blue background colour, appears.

Here is a minimal working example:

\documentclass{book}

\usepackage{xcolor}

\usepackage{pdfcomment}

\begin{document}

\pdftooltip{foo}{%
\colorbox{blue}{%
Hint: What is the definition of foo?}% End of Colorbox
}% End of pdftooltip command

\end{document}

(Well it compiles without complaining, but it does not give the expected result :-( )

However, there is no blue background colour but an almost verbatim text of colorbox ... blue etc., bracketed by (presumably) pdf code.

I know, that there is the possibility of mathematical markup in pdftooltips, but what about "eye candy"? ;-)

Edited: I know of the packages fancytooltips or cooltooltips but they do not match my intents

4
  • 2
    Something like tex.stackexchange.com/a/108998 ?
    – AlexG
    Jun 19, 2013 at 14:09
  • @AlexG: Thanks a lot for that link, but I've already seen that thread. Dragging around the tooltip box is not necessary, apart from the security issues by using fancytooltips and its insertion of javascript code into Adobe Reader. I also want to have the tooltip statement also in my problem environment and not in a separate external file, as required by fancytooltips (or have I misunderstood some options/features of that package?)
    – user31729
    Jun 19, 2013 at 14:22
  • What you see in the answer I linked does not use fancytooltips. The tooltip is inserted inline, no external file as requested. Moving the tooltip around is just a bonus feature (The tip text could be wider than the page).
    – AlexG
    Jun 19, 2013 at 14:42
  • 1
    As for JavaScript, no risk no fun ;).
    – AlexG
    Jun 19, 2013 at 15:03

1 Answer 1

26
\tooltip[black]{foo}[blue!50]{Hint: What is the definition of foo?}

If the mouse is moved over 'foo' the tip is shown and it disappears immediately when the mouse is moved out.

In order to drag the tip around, 'foo' must be clicked. The tip remains visible. Move the mouse over the tip, click it and move it around. Click the tip once more to pin it down at the current position.

To hide the tip, wipe over 'foo' with the mouse.

Link text and tip text colours are optional. Besides pdftex, all common drivers (xetex, dvips, ...) are supported.

It is recommended that <tip text> is not wider than \linewidth, <tiptext> should be put into a \parbox if necessary.

(Code by M. Scharrer from https://tex.stackexchange.com/a/17808 is used to compute initial left-shift for wider tip text boxes.)

enter image description here

%\documentclass[a6paper,12pt]{scrbook}
\documentclass[12pt]{scrbook}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% tooltips with LaTeX v. 2017/11/28
%
% \tooltip[*[*[*[*]]]][<link colour>]{<link text>}[<tip box colour>]{<tip text>}
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%   \tooltip     --> draggable tip, visible on mouse-over, hidden on mouse-out
%               
%   \tooltip*    --> draggable tip, toggle visiblity on mouse-over
%               
%   \tooltip**   --> NON-draggable tip, visible on mouse-over, hidden on mouse-out
%              
%   \tooltip***  --> NON-draggable tip, toggle visiblity on mouse-over
%               
%   \tooltip**** --> NON-draggable tip, toggle visiblity on mouse-click (Evince!)
%
% Default link colour can be set with
%
%   \usepackage[linkcolor=<colour>]{hyperref}
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\usepackage{pdfbase}[2017/03/16]
\usepackage{xparse,ocgbase}
\usepackage{xcolor,calc}
\usepackage{tikzpagenodes}
\usetikzlibrary{calc}

\ExplSyntaxOn
\let\tpPdfLink\pbs_pdflink:nn
\let\tpPdfAnnot\pbs_pdfannot:nnnn\let\tpPdfLastAnn\pbs_pdflastann:
\let\tpAppendToFields\pbs_appendtofields:n
\def\tpPdfXform{\pbs_pdfxform:nnnnn{1}{1}{}{}}
\let\tpPdfLastXform\pbs_pdflastxform:
\ExplSyntaxOff

\makeatletter
\NewDocumentCommand{\tooltip}{%
  ssssO{\ifdefined\@linkcolor\@linkcolor\else blue\fi}mO{yellow!20}m%
}{{%
  \leavevmode%
  \IfBooleanT{#2}{%
    %for variants with two and more stars, put tip box on a PDF Layer (OCG)
    \ocgbase@new@ocg{tipOCG.\thetcnt}{%
      /Print<</PrintState/OFF>>/Export<</ExportState/OFF>>%
    }{false}%
    \xdef\tpTipOcg{\ocgbase@last@ocg}%
    %prevent simultaneous visibility of multiple non-draggable tooltips
    \ocgbase@add@ocg@to@radiobtn@grp{tool@tips}{\ocgbase@last@ocg}%
  }%
  \tpPdfLink{%
    \IfBooleanTF{#4}{%
      /Subtype/Link/Border[0 0 0]/A <</S/SetOCGState/State [/Toggle \tpTipOcg]>>
    }{%
      /Subtype/Screen%
      /AA<<%
        \IfBooleanTF{#3}{%
          /E<</S/SetOCGState/State [/Toggle \tpTipOcg]>>%
        }{%  
          \IfBooleanTF{#2}{%
            /E<</S/SetOCGState/State [/ON \tpTipOcg]>>%
            /X<</S/SetOCGState/State [/OFF \tpTipOcg]>>%
          }{
            \IfBooleanTF{#1}{%
              /E<</S/JavaScript/JS(%
                var fd=this.getField('tip.\thetcnt');%
                if(typeof(click\thetcnt)=='undefined'){%
                  var click\thetcnt=false;%
                  var fdor\thetcnt=fd.rect;var dragging\thetcnt=false;%
                }%
                if(fd.display==display.hidden){%
                  fd.delay=true;fd.display=display.visible;fd.delay=false;%
                }else{%
                  if(!click\thetcnt&&!dragging\thetcnt){fd.display=display.hidden;}%
                  if(!dragging\thetcnt){click\thetcnt=false;}%
                }%
                this.dirty=false;%
              )>>%
            }{%
              /E<</S/JavaScript/JS(%
                var fd=this.getField('tip.\thetcnt');%
                if(typeof(click\thetcnt)=='undefined'){%
                  var click\thetcnt=false;%
                  var fdor\thetcnt=fd.rect;var dragging\thetcnt=false;%
                }%
                if(fd.display==display.hidden){%
                  fd.delay=true;fd.display=display.visible;fd.delay=false;%
                }%
               this.dirty=false;%
              )>>%
              /X<</S/JavaScript/JS(%
                if(!click\thetcnt&&!dragging\thetcnt){fd.display=display.hidden;}%
                if(!dragging\thetcnt){click\thetcnt=false;}%
                this.dirty=false;%
              )>>%
            }%  
            /U<</S/JavaScript/JS(click\thetcnt=true;this.dirty=false;)>>%
            /PC<</S/JavaScript/JS (%
              var fd=this.getField('tip.\thetcnt');%
              try{fd.rect=fdor\thetcnt;}catch(e){}%
              fd.display=display.hidden;this.dirty=false;%
            )>>%
            /PO<</S/JavaScript/JS(this.dirty=false;)>>%
          }%
        }%
      >>%
    }%
  }{{\color{#5}#6}}%
  \sbox\tiptext{%
    \IfBooleanT{#2}{%
      \ocgbase@oc@bdc{\tpTipOcg}\ocgbase@open@stack@push{\tpTipOcg}}%
    \fcolorbox{black}{#7}{#8}%
    \IfBooleanT{#2}{\ocgbase@oc@emc\ocgbase@open@stack@pop\tpNull}%
  }%
  \edef\twd{\the\wd\tiptext}%
  \edef\tht{\the\ht\tiptext}%
  \edef\tdp{\the\dp\tiptext}%
  \measureremainder{\whatsleft}\tipshift=0pt%
  \ifdim\whatsleft<\twd\setlength\tipshift{\whatsleft-\twd}\fi%
  \IfBooleanF{#2}{\tpPdfXform{\tiptext}}%
  \raisebox{\heightof{#6}+\tdp}[0pt][0pt]{\makebox[0pt][l]{\hspace{\tipshift}%
    \IfBooleanTF{#2}{\usebox{\tiptext}}{%
      \tpPdfAnnot{\twd}{\tht}{\tdp}{%
        /Subtype/Widget/FT/Btn/T (tip.\thetcnt)%
        /AP<</N \tpPdfLastXform>>%
        /MK<</TP 1/I \tpPdfLastXform/IF<</S/A/FB true/A [0.0 0.0]>>>>%
        /Ff 65536/F 3%
        /AA <<%
          /U <<%
            /S/JavaScript/JS(%
              var fd=event.target;%
              var mX=this.mouseX;var mY=this.mouseY;%
              var drag=function(){%
                var nX=this.mouseX;var nY=this.mouseY;%
                var dX=nX-mX;var dY=nY-mY;%
                var fdr=fd.rect;%
                fdr[0]+=dX;fdr[1]+=dY;fdr[2]+=dX;fdr[3]+=dY;%
                fd.rect=fdr;mX=nX;mY=nY;%
              };%
              if(!dragging\thetcnt){%
                dragging\thetcnt=true;Int=app.setInterval("drag()",1);%
              }%
              else{app.clearInterval(Int);dragging\thetcnt=false;}%
              this.dirty=false;%
            )%
          >>%
        >>%
      }%
      \tpAppendToFields{\tpPdfLastAnn}%
    }%
  }}%
  \stepcounter{tcnt}%
}}
\makeatother
\newsavebox\tiptext\newcounter{tcnt}
\newlength{\whatsleft}\newlength{\tipshift}
\newcommand{\measureremainder}[1]{%
  \begin{tikzpicture}[overlay,remember picture]
    \path let \p0 = (0,0), \p1 = (current page.east) in
      [/utils/exec={\pgfmathsetlength#1{\x1-\x0}\global#1=#1}];
  \end{tikzpicture}%
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{document}
\tooltip[black]{foo}[blue!50]{Hint: What is the definition of foo?}

with non-draggable tooltip: \tooltip**[black]{bar}[blue!50]{Hint: What is the definition of bar?}
\end{document}
26
  • Works well. But, shouldn't the tool tip go away upon mouse moving away? This requires a mouse over to toggle it on, and another mouse over to toggle it off. Jun 19, 2013 at 15:05
  • @Peter: I tried hard to implement this, but if one tries to relocate the tip box (the bonus feature), the mouse inevitably leaves the link area and the tip would be hidden.
    – AlexG
    Jun 19, 2013 at 15:08
  • 1
    @Megachip. Done.
    – AlexG
    Nov 18, 2013 at 12:41
  • 1
    @1010011010: No problem here with (frozen) TL-13.
    – AlexG
    May 19, 2014 at 6:41
  • 1
    Ok, the fixed the code will compile and work again, hopefully.
    – AlexG
    Nov 23, 2015 at 11:30

You must log in to answer this question.