Anker im Inhaltsverzeichnis - geht das?

Fragen und Probleme, die nicht den obigen Kategorien zugeordnet werden können


Rolli
Forum-Guru
Forum-Guru
Beiträge: 345
Registriert: Mi 15. Feb 2017, 08:50
Wohnort: Mittelfranken

Anker im Inhaltsverzeichnis - geht das?

Beitrag von Rolli »

Hallo!

Ich möchte Folgendes:
Alle Überschriften im laufenden Text (also \chapter (sofern vorhanden), \section, \subsection, ...) sollen anklickbar sein. Beim Anklicken soll in das
Inhaltsverzeichnis gesprungen werden, an die korrekte Stelle.

Also im Beispiel:

Klick auf "3 Drittens" auf Seite 3 soll ergeben, dass "3 Drittens" auf Seite 1 (im Inhaltsverzeichnis) angezeigt wird.

So wie ich das im Beispiel gemacht habe, geht es natürlich nicht. Man müsste dafür im Inhaltsverzeichnis Anker setzen können.

Geht das?

Code: Alles auswählen

\documentclass{scrartcl}
\usepackage{blindtext}
\usepackage{hyperref}

\begin{document}

\tableofcontents

\section{\href{Erstens}{Erstens}}
\Blindtext
\section{\href{Zweitens}{Zweitens}}
\Blindtext
\section{\href{Drittens}{Drittens}}
\Blindtext

\end{document}
Gruß vom Rolli

Bartman
Forum-Meister
Forum-Meister
Beiträge: 2138
Registriert: Do 16. Jul 2009, 21:41
Wohnort: Hessische Provinz

Beitrag von Bartman »

Die Antworten zu Linking the section text to the TOC betreffen Standardklassen. Vielleicht lässt sich eine der Lösungen auf KOMA-Script übertragen.

Gast

Beitrag von Gast »

Man muss dazu eigentlich nur in die Verzeichniseinträge einen Anker einschleusen und in die Ausgabe der Überschriften den Sprung zu diesem Anker.

Die Anker kann man bei KOMA-Script auf zwei Arten einschleusen: Entweder man deklariert den Verzeichnisstil der einzelnen Einträge über \DeclareTOCStyleEntry oder \RedeclareSectionCommands um (theoretisch kann man dazu auch zunächst einen neuen Stil definieren, der die Anker direkt erzeugt) oder man nimmt über \addtocentrydefault Einfluss darauf, was in das Inhaltsverzeichnis geschrieben wird. Dabei muss man aber beachten, dass hyperref diese Texte davon auch für die Bookmaarks verwendet, also ggf. hier zusätzlich mit \textorpdfstring gearbeitet werden sollte.

Den Sprung zum Anker kann man einfach in die Ausgabe der Überschriften \sectionnlinesformat und \sectioncatchphraseformat einfügen.

Um fortlaufende Anker zu erzeugen böte sich theoretisch der Zähler der jeweiligen Gliederungsebene an. Allerdings funktioniert das dann nur für nummerierte Überschriften. Besser ist daher, einen eigenen Zähler zu verwenden. Dann funktioniert es auch für nicht nummerierte Überschriften.

Code: Alles auswählen

\documentclass{scrartcl}
\usepackage{blindtext}
\usepackage{xpatch}
\usepackage{hyperref}

\newcounter{tocentrynumber}
\xpatchcmd{\addtocentrydefault}{#3}{%
  \texorpdfstring{\protect\hypertarget{tocentry.\thetocentrynumber}{#3}}{#3}%
}{}{\undefined}
\makeatletter
\renewcommand*{\sectionlinesformat}[4]{%
  \stepcounter{tocentrynumber}%
  \hyperlink{tocentry.\thetocentrynumber}{\@hangfrom{\hskip #2#3}{#4}}%
}
\makeatother
\renewcommand*{\sectioncatchphraseformat}[4]{%
  \stepcounter{tocentrynumber}%
  \hyperlink{tocentry.\thetocentrynumber}{\hskip #2#3#4}%
}

\begin{document}
\tableofcontents

\section{Erstens}
\Blindtext
\section{Zweitens}
\Blindtext
\section{Drittens}
\Blindtext
\addsec{Nichtnummeriertens}
\Blindtext

\blinddocument
\blinddocument
\blinddocument
\blinddocument

\end{document}
Zu beachten ist allerdings, dass diverse Pakete leider nicht \addsectiontocentry o. ä. und damit auch nicht \addtocentrydefault verwenden, um eigene Einträge im Inhaltsverzeichnis vorzunehmen. Das ist dann aber ein Problem dieser Pakete. Wollte man hier eingreifen müsste man in der Tat den Verzeichnisstil der Einträge manipulieren (siehe Hinweis oben) oder direkt \addcontentsline oder sogar \addtocontents umdefinieren.

Rolli
Forum-Guru
Forum-Guru
Beiträge: 345
Registriert: Mi 15. Feb 2017, 08:50
Wohnort: Mittelfranken

Beitrag von Rolli »

Hi,

danke für den Tipp - ich bin immer wieder erstaunt ...
Im Overleaf geht es übrigens (warum auch immer) nicht.

Es hat nur noch einen winzigen Schönheitsfehler: Klicken auf eine Überschrift im laufenden Text springt n a c h dem Eintrag ins Inhaltsverzeichnis; d.h. der Anker scheint hinter dem Überschrifts-Text zu sein. Wie bekommt man den vor den Überschrifts-Text?

Ich vermute mal, das geht irgendwie mit \xpretocmd? Leider bin ich noch nicht so tief in den Niederungen ...

Gruß vom Rolli

Gast

Beitrag von Gast »

Eigentlich ist der gesamte Text der Überschrift im Inhaltsverzeichnis der Anker. Man könnte natürlich auch (ungestestet!)

Code: Alles auswählen

\xpatchcmd{\addtocentrydefault}{#3}{%
  \texorpdfstring{\protect\hypertarget{tocentry.\thetocentrynumber}{}}{}#3%
}{}{\undefined}
verwenden, um den Anker unmittelbar vor dem Text einzufügen. Das dürfte aber kaum etwas verändern.

Man könnte den Anker bei nummerierten Einträgen auch bereits in der Nummer einfügen (ungetestet!):

Code: Alles auswählen

\makeatletter
\newcommand{\addtocentrydefault}[3]{%
  \IfArgIsEmpty{#2}{%
    \expandafter\tocbasic@addxcontentsline\expandafter{\ext@toc}{#1}{#2}{%
      \texorpdfstring{\protect\hypertarget{tocentry.\thetocentrynumber}{}}{}#3%
    }%
  }{%
    \expandafter\tocbasic@addxcontentsline\expandafter{\ext@toc}{#1}{%
      \texorpdfstring{\protect\hypertarget{tocentry.\thetocentrynumber}{}}{}#2%
    }{#3}%
  }%
}
\makeatother
Mehr Kontrolle über die Position des Ankers hat man ggf. über den Verzeichnisstil. Spätestens wenn man sich einen komplett eigenen Verzeichnisstil definiert, kann man da machen, was immer man will. Siehe dazu das Kapitel zu tocbasic in der KOMA-Script-Anleitung.

Der Status Rückfrage ist übrigens nicht für Ergänzungsfragen durch den Fragesteller. Bitte informiere dich über die korrekte Bedeutung (einfach mit der Maus über das Fragezeichen bei "Status aktuellen halten" fahren).

Gast

Beitrag von Gast »

Bei mir funktioniert das übrigens auch mit dem von Overleaf heruntergeladenen PDF. Nur im Overleaf-Previewer funktioniert es nicht, aber dort funktionieren bei mir Links häufig nicht. Bis vor kurzem haben bei mir dort Links überhaupt nicht funktioniert. Das Feature scheint schlicht noch in Entwicklung zu sein.

Rolli
Forum-Guru
Forum-Guru
Beiträge: 345
Registriert: Mi 15. Feb 2017, 08:50
Wohnort: Mittelfranken

Beitrag von Rolli »

Danke erstmal für die Hilfestellung soweit.
Untenstehendes bringt den Fehler

Code: Alles auswählen

 Command \addtocentrydefault already defined. 
.
Wenn ich

Code: Alles auswählen

 \newcommand{\addtocentrydefault} 
in

Code: Alles auswählen

 \renewcommand{\addtocentrydefault} 
ändere, geht es zwar beim ersten Texifien; beim zweiten Durchlauf (für das Einfügen der Hyperlinks) kommt jedoch die Fehlermeldung

Code: Alles auswählen

 ! Undefined control sequence. \@hyper@@anchor ...r@spot {#2#3}\let \put@me@back \@empty \ifx \relax #2\rel... 
.

Leider bin ich noch nicht so in den Tiefen der Package-Programmierung drin, dass mir diese Fehlermeldung mehr als "Bahnhof" sagt ...

Über die kommenden ruhigeren Tage schaue ich mir mal tocbasic an - nochmals Dank für den Tipp. Bis dahin wird es wohl so bleiben, falls nicht noch jemand eine zündende Idee hat.

Gruß vom Rolli

Code: Alles auswählen

\documentclass{scrartcl}
\usepackage{blindtext}
\usepackage{xpatch}
\usepackage{hyperref}

\newcounter{tocentrynumber}
\makeatletter
\newcommand{\addtocentrydefault}[3]{%
  \IfArgIsEmpty{#2}{%
    \expandafter\tocbasic@addxcontentsline\expandafter{\ext@toc}{#1}{#2}{%
      \texorpdfstring{\protect\hypertarget{tocentry.\thetocentrynumber}{}}{}#3%
    }%
  }{%
    \expandafter\tocbasic@addxcontentsline\expandafter{\ext@toc}{#1}{%
      \texorpdfstring{\protect\hypertarget{tocentry.\thetocentrynumber}{}}{}#2%
    }{#3}%
  }%
}
\makeatother

\begin{document}

\tableofcontents

\section{Erstens}
\Blindtext
\section{Zweitens}
\Blindtext
\section{Drittens}
\Blindtext
\addsec{Nichtnummeriertens}
\Blindtext

\blinddocument
\blinddocument
\blinddocument
\blinddocument

\end{document}
Zuletzt geändert von Rolli am Fr 7. Dez 2018, 13:22, insgesamt 1-mal geändert.

Gast

Beitrag von Gast »

Bei einer Lösung über den Eintragsstil könnte es allerdings etwas aufwändiger werden, den laufenden Zähler für die Einträge zu bestimmen. Man kann das sicher lösen (beispielsweise indem man die Erhöhung des Zählers getrennt in die toc-Datei schreibt oder indem man für jede Ebene einen eigenen Zähler verwenden oder indem man nur dann den Zähler erhöht, wenn man tatsächlich eine Ebene setzte, die einen Eintrag im Inhaltsverzeichnis hat, oder indem man einfach alle Ebenen im Inhaltsverzeichnis ausgeben lässt), aber es ist nicht so einfach wie oben gezeigt.

Gast

Beitrag von Gast »

Wenn es ein Problem ist, dass der PDF-Viewer zur linken unteren Ecke eines Targets springt statt zur linken oberen Ecke, dann kann man das Target ggf. recht einfach vertikal verschieben:

Code: Alles auswählen

\documentclass{scrartcl}
\usepackage{blindtext}
\usepackage{xpatch}
\usepackage{hyperref}

\newcounter{tocentrynumber}
\xpatchcmd{\addtocentrydefault}{#3}{%
  \texorpdfstring{\protect\xhyperdummytarget{tocentry.\thetocentrynumber}}{}%
  #3%
}{}{\undefined}
\newcommand*{\xhyperdummytarget}[1]{%
  \smash{\raisebox{\ht\strutbox}{\hypertarget{#1}{\strut}}}%
}
\makeatletter
\renewcommand*{\sectionlinesformat}[4]{%
  \stepcounter{tocentrynumber}%
  \hyperlink{tocentry.\thetocentrynumber}{\@hangfrom{\hskip #2#3}{#4}}%
}
\makeatother
\renewcommand*{\sectioncatchphraseformat}[4]{%
  \stepcounter{tocentrynumber}%
  \hyperlink{tocentry.\thetocentrynumber}{\hskip #2#3#4}%
}

\begin{document}
\tableofcontents

\section{Erstens}
\Blindtext
\section{Zweitens}
\Blindtext
\section{Drittens}
\Blindtext
\addsec{Nichtnummeriertens}
\Blindtext

\blinddocument
\blinddocument
\blinddocument
\blinddocument

\end{document}
Eine Möglichkeit über den Eintragsstil zu arbeiten wäre übrigens:

Code: Alles auswählen

\documentclass{scrartcl}
\usepackage{blindtext}
\usepackage{xpatch}
\usepackage{hyperref}

\newcommand*{\anchortocentry}[1]{%
  \smash{\raisebox{\ht\strutbox}{\hypertarget{\nexttocentry}{\strut}}}\ignorespaces#1%
}
\BeforeStartingTOC[toc]{\newcommand*{\nexttocentry}{page.0}}
\newcounter{tocentrynumber}
\RedeclareSectionCommands[tocentryformat=\anchortocentry]{section,subsection,subsubsection,paragraph,subparagraph}
\makeatletter
\renewcommand*{\sectionlinesformat}[4]{%
  \stepcounter{tocentrynumber}%
  \addtocontents{\ext@toc}{\protect\def\protect\nexttocentry{tocentry.\thetocentrynumber}}%
  \hyperlink{tocentry.\thetocentrynumber}{\@hangfrom{\hskip #2#3}{#4}}%
}
\renewcommand*{\sectioncatchphraseformat}[4]{%
  \stepcounter{tocentrynumber}%
  \addtocontents{\ext@toc}{\protect\def\protect\nexttocentry{tocentry.\thetocentrynumber}}%
  \hyperlink{tocentry.#1.\thetocentrynumber}{\hskip #2#3#4}%
}
\makeatother

\begin{document}
\tableofcontents

\section{Erstens}
\Blindtext
\subsection{Suberstens}
\blindtext
\subsubsection{Subsuberstens}
\blindtext
\subparagraph{Paraerstens}
\blindtext
\section{Zweitens}
\Blindtext
\section{Drittens}
\Blindtext
\addsec{Nichtnummeriertens}
\Blindtext

\blinddocument
\blinddocument
\blinddocument
\blinddocument

\end{document}
wie zu sehen ist, habe ich auch da den Anker verschoben. Es gibt sicher diverse andere Möglichkeiten. So könnte man statt eines eigenen Zählers beispielsweise auch auf den von hyperref erzeugten zurückgreifen und diesen um einen Präfix erweitern. Manche Lösungen sind raffinierter als andere, manche sind schöner, mancher sind leichter zu verstehen. Das ist bei TeX oft so.

Rolli
Forum-Guru
Forum-Guru
Beiträge: 345
Registriert: Mi 15. Feb 2017, 08:50
Wohnort: Mittelfranken

Beitrag von Rolli »

Super, danke - das mit dem Anker verschieben klappt.
Trotzdem schaue ich mir's mal an ...

Gruß vom Rolli

Antworten