# Automating the process of passing the overlay number to \hypertarget in beamer

I'm trying to use the suggestion by @gonzalo_medina in this thread about hyperlinks and the suggestion by @diabonas in this thread about overlay numbers to automate the process of passing an overlay number to \hypertarget

The method I'm using is very clumsy, and I'm sure there's a better way using beamer's internal functionality. But this is what I've tried, borrowing very liberally from @gonzalo_median's code

\documentclass{beamer}
\usepackage{ifthen}
\makeatletter
\newcommand*{\overlaynumber}{\number\beamer@slideinframe}
\makeatother
\begin{document}
\begin{frame}
\end{frame}
\begin{frame}
\begin{itemize}[<+->]
\item First.
\pause
\item Second.
\pause
\item Third;
\pause
\item
\ifthenelse{\isundefined{\firstValue}}{\def\firstValue{\overlaynumber}}{}
Fourth;  I'm now at overlay
\#\firstValue.  \hypertarget<\firstValue>{label4}{\beamerbutton{I'm on the fourth slide}}
\pause
\item Fifth
\pause
\item
\ifthenelse{\isundefined{\secondValue}}{\def\secondValue{\overlaynumber}}{}
Sixth I'm now on overlay \#\secondValue   \hypertarget<\secondValue>{label6}{\beamerbutton{I'm on the sixth slide}}
\end{itemize}
\end{frame}
\end{document}


The problem I've identified with the code (there maybe others) is that even though I've specified that \firstValue and \secondValue should be defined only if they haven't already been defined, the ifthen conditional isn't working and the values keep getting incremented along with \overlaynumber. The problem should be evident immediately from running the code

If somebody could get this running properly, or suggest a better approach, I'd be most grateful.

• BTW, the \pause commands appear to be redundant to \item. – John Kormylo Sep 15 '17 at 17:36
• Aha! Use \gdef (global definition), or just count the frames. – John Kormylo Sep 15 '17 at 18:14

As John Kormylo already pointed out, the complete slide is processed each time an overlay is typeset, so \firstValue and \secondValue will already be defined on the very first overlay (if you use \global\edef instead of \def, otherwise the definition will be local to the current overlay), even if the corresponding overlay is only shown later.

However, there is a much easier solution: just use the <.> overlay specification to place to \hypertarget only on the current overlay. This works as the dot returns the current value of the counter beamerpauses minus one. In contrast to the internally used counter \beamer@slideinframe, the beamerpauses counter is only incremented after each \pause (explicit or implicit by using an overlay specification like <+->) - try using \arabic{beamerpauses} and \overlaynumber for comparison.

So your example becomes as simple as

\documentclass{beamer}

\begin{document}
\begin{frame}
\end{frame}

\begin{frame}
\begin{itemize}[<+->]
\item First \arabic{beamerpauses}\overlaynumber
\item Second
\item Third
\item Fourth \hypertarget<.>{label4}{\beamerbutton{I'm on the fourth slide}}
\item Fifth
\item Sixth \hypertarget<.>{label6}{\beamerbutton{I'm on the sixth slide}}
\end{itemize}
\end{frame}
\end{document}

• Fabulous, thanks. I knew there had to be a simple way. – Leo Simon Sep 16 '17 at 13:04

Beamer uses two counts: \beamer@slideinframe and \beamer@minimum. A slide first becomes visible when the two are equal.

\documentclass{beamer}
\usepackage{ifthen}

\makeatletter
\newcommand*{\overlaynumber}{\number\beamer@minimum}
\makeatother

\begin{document}
\begin{frame}
\end{frame}
\begin{frame}
\begin{itemize}[<+->]
\item First.
\item Second.
\item Third;
\item Fourth;  I'm now at overlay \#\overlaynumber
\only<\overlaynumber>{\hypertarget{label4}{\beamerbutton{I'm on the fourth slide}}}
\item Fifth;  I'm now on overlay \#\overlaynumber
\hypertarget<\overlaynumber>{label6}{\beamerbutton{I'm on the fifth slide}}
\item Sixth
\end{itemize}
\end{frame}
\end{document}

• thanks for this John. But your suggestion still requires manually monitoring which overlay I've reached. I'm trying to automate that process, so that, for example, if I added a line or two above the hypertarget, then I wouldn't have to recompute the 4 and the 5. I'd be able to do this if I could just somehow successfully save the overlay number the first time it was invoked, e.g., \ifthenelse{\isundefined{\firstOverlay}}{\def\firstOverlay{\overlaynumber}}{} but this just refuses to work for me. – Leo Simon Sep 15 '17 at 23:47
• The code is executed EVERY time (inside a savebox). Even \protected#write couldn't tell the difference between the visible or invisible overlays. – John Kormylo Sep 16 '17 at 4:52
• Thanks, John. Does this means there's absolutely no available way to automate the process specification? Or more specifically, absolutely impossible to define a variable only first time it's processed, and then leave it with the original value? It seems that the \ifthenelse command is simply not working. – Leo Simon Sep 16 '17 at 7:07
• Actually, the answer is trivial. Beamer provides another count which does precisely what you want. – John Kormylo Sep 16 '17 at 13:23