# Relative Order of Overlays in Beamer

I am creating a presentation with beamer using relative overlays. When the order overlays should appear in is different from the order the tex code is parsed things become difficult (see e.g. relative overlays).

## First Part

Consider the following example. It is not easy to understand the order of appearance, and neither is it easy to come up with the code to achieve the desired order. With more complicated code things become very unwieldy.

Note that I do not care whether the overlays contain list items or tikz elements or something. It should be a general solution.

Currently:

\documentclass{beamer}
\begin{document}
\begin{frame}
\begin{itemize}
\item<+(2)-> First item, appears third
\item<+(-1)-> Second item, appears first
\item<+(1)-> Third item, appears fourth
\item<+(-2)-> Fourth item, appears second
\end{itemize}
\end{frame}
\end{document}


I would like to know if there is a way to define the order of overlays independent of the order of appearance in the document. A possible example is given at below.

Wanted (Does not compile)

\documentclass{beamer}
\begin{document}
\begin{frame}
\begin{itemize}
\item<foo1> First item, appears third
\item<foo2> Second item, appears first
\item<foo3> Third item, appears fourth
\item<foo4> Fourth item, appears second
\end{itemize}
\setorder{foo2, foo4, foo1, foo3}
\end{frame}
\end{document}


## Second Part

Additionally, I would like that overlays also can disappear. Consider the following command. The intention is that the first overlay shows the items labeled by foo1 and foo3. The second overlay shows the items labeled by foo1 and foo2, etc.

\setorder{ {foo1, foo3}, {foo1, foo2}, {foo3, foo4}, {foo2, foo4} }

Not really symbolic overlay specifications, but an easy attempt towards your first problem:

\documentclass{beamer}
\usepackage{etoolbox}

\def\againframeorder<#1>#2{%
\def\do##1{\againframe<##1>{#2}}
\docsvlist{#1}%
}

\setbeamercovered{transparent}

\begin{document}
\begin{frame}<beamer:0>[label=foo]
\begin{itemize}
\item<1> First item, appears third
\item<2> Second item, appears first
\item<3> Third item, appears fourth
\item<4> Fourth item, appears second
\end{itemize}
\end{frame}

\againframeorder<2,4,1,3>{foo}

\end{document}


Basically, we use the absolute overlay numbers as "symbols" here, but do not ship out the respective frames (<beamer:0>). We then use a loop with \againframe to ship them out in the intended order.

• can't you do that directly? \begin{frame}<2,4,1,3> ... – yo' Feb 27 '15 at 16:43
• @yo' Unfortunately not, as the overlay spec only defines which slides of a frame are shown, but not their order. So the result would be the same as in \begin{frame}<1-4>. – Daniel Feb 28 '15 at 23:19

After some time I got the 'setorder' command working, which makes the example relatively easy to define. I will try to use it and see whether its useful. Sorry for the bad indention.

I asked an extended version of this question on this site.

\documentclass{beamer}
\usepackage{xstring}
\usepackage{etoolbox}
\usepackage{tikz}
\newcounter{mycounter}

% #1 is of the form <name>[=-|n], e.g. foo=- or foo=10 or foo
% Stores in #2 the overlay specification for <name> s.t. it can be appended to the content of <name>
\newcommand*{\getNewOverlayContent}[2]{%
\getItemSpec{#1}{itemSpec}%
\IfStrEq{\itemSpec}{-}{%
\csedef{#2}{\arabic{beamerpauses}-}%
}{%
\IfStrEq{\itemSpec}{}{%
\csedef{#2}{\arabic{beamerpauses}}%
}{%
\IfInteger{\itemSpec}{%
%               \mycounter=\
\setcounter{mycounter}{\arabic{beamerpauses}}%
\csedef{#2}{\arabic{beamerpauses}-\arabic{mycounter}}%
}{%
\PackageError{setorder}{Argument has illegal format}{Argument was #1}%
}%
}%
}%
%   input: #1, itemspec:\itemSpec, beamervalue: \arabic{beamerpauses}, content: \csuse{#2} \\
}
% #1 is of the form 'foo=1' or 'foo=-' or 'foo'.
% #2 Is the name of the macro which should hold the result
% This macro stores the part infront '=' (the name) in #2.
\newcommand*{\getItemName}[2]{%
\IfSubStr{#1}{=}{%
\StrBefore{#1}{=}[\tmp]%
\csdef{#2}{\tmp}%
}{%
\csdef{#2}{#1}%
}%
}
% #1 is of the form 'foo=1' or 'foo=-' or 'foo'.
% #2 Is the name of the macro which should hold the result
% This macro stores the part behind '=' (the overlay spec) in #2. The stored part is empty iff there is no '=' in #1
\newcommand*{\getItemSpec}[2]{%
\StrBehind{#1}{=}[\tmp]%
\csdef{#2}{\tmp}%
}
% #2 is the name where content should be appended.
% It has been ensured previously that #2 is a defined macro
% #1 is the content to append
% Depending on whether #2 is empty or not a (,) is added
% before appending #1
\newcommand*{\appendToOverlaySpecification}[2]{%
\IfStrEq{\csexpandonce{#2}}{}{%
% #1 i.e. <name> is empty
\cseappto{#2}{\csname#1\endcsname}%
}{%
\cseappto{#2}{,\csname#1\endcsname}%
}%
}

\newcommand*{\setorderItem}[1]{%
\getNewOverlayContent{#1}{overlaycontent}%
\getItemName{#1}{cmdname}%
\appendToOverlaySpecification{overlaycontent}{\cmdname}%
}

\newcommand*{\setorderList}[1]{%
\forcsvlist{\setorderItem}{#1}%
\stepcounter{beamerpauses}%
}
\newcommand*{\setorder}[1]{%
\clearNamesListofLists{#1}%
\forcsvlist{\setorderList}{#1}%
}

% takes a list of lists of the form: {foo=1, bla},{gar=-} and then defines empty macros for each name
\newcommand*{\clearNamesListofLists}[1]{%
\forcsvlist{    \clearNamesList}{#1}%
}
\newcommand*{\clearNamesList}[1]{%
\forcsvlist{    \clearName}{#1}%
}
\newcommand*{\clearName}[1]{%
\getItemName{#1}{cmdname}%
\csdef{\cmdname}{}%
}
\begin{document}
\begin{frame}{Each overlay one item}
\setorder{{seconditem},{fourthitem},{firstitem},{thirditem}}

\begin{itemize}
\item<\firstitem> First item, appears third
\item<\seconditem> Second item, appears first
\item<\thirditem> Third item, appears fourth
\item<\fourthitem> Fourth item, appears second
\end{itemize}
\end{frame}

\begin{frame}{More complex example}
\setorder{{seconditem=2},{fourthitem},{firstitem=-},{thirditem=-}}
\begin{itemize}
\item<\firstitem> First item, appears third, does not disappear
\item<\seconditem> Second item, appears first, stays 2 slides
\item<\thirditem> Third item, appears fourth, does not disappear
\item<\fourthitem> Fourth item, appears second, stays 1 slide
\end{itemize}
\begin{tikzpicture}
\node<\seconditem> (foo1) [draw] {For second item};
\node<\fourthitem> (foo2) [draw, below of=foo1] {For fourth item};
\node<\firstitem> (foo3) [draw, right of=foo1, node distance=3.5cm] {For first item};
\node<\thirditem> (foo4) [draw, below of=foo3] {For third item};
\end{tikzpicture}
\end{frame}
\end{document}