35

Is it possible to have a clickable "copy to clipboard" feature in a PDF document generated by LaTeX?

Ideally in the form of a macro that also allows for graphical elements to be embedded inside it (to make, say, a custom button that, when clicked, copies something to the clipboard).

Edit: An Acrobat only solution will work too.

steve
  • 2,154
1010011010
  • 6,357
  • Possibly related: http://tex.stackexchange.com/questions/117792/listings-copy-to-clipboard-feature – 1010011010 May 01 '14 at 10:48
  • 6
    There is the \Acrobatmenu command from hyperref package, but apart from printing, saving-as and open I did not manage to get other options working, although there are some of them, as written in the hyperref manual, amongst them Copy etc. Perhaps, H. Oberdiek knows more ;-) –  May 01 '14 at 21:05
  • Which clipboard? And which PDF viewer? – cfr May 04 '14 at 19:34
  • @cfr The system clipboard. Same as what Ctrl+C does. The most general solution is the best solution. – 1010011010 May 04 '14 at 19:35
  • 4
    That's already platform-specific. OS X doesn't use ctrl+c. (At least in Aqua - can't remember about X11 assuming it still supports that.) I guess Windows does. GNU/Linux may or may not depending on how it is set up. I'm guessing if this is possible, it will be viewer-specific and maybe only possible in acroread, maybe with javascript enabled. Like Christian Hupfer, I never had any luck getting this kind of thing working with hyperref but take a look - it is certainly a while since I tried it. – cfr May 04 '14 at 19:38
  • The idea of storing some text on the fly is not platform-specific, though, is it? – 1010011010 May 04 '14 at 19:40
  • @ChristianHupfer I did not find the Copy command that you were referring to in the hyperref manual? – 1010011010 May 06 '14 at 16:08
  • \Acrobatmenu{Copy}{Name of Button}, where you can change of Name of Button to whatever you like, but as cfr wrote: Most of the \Acrobatmenu stuff does not work. –  May 06 '14 at 16:35
  • 1
    @Euryris: Here is the HTML version of the hyperref manual, for example: ftp://ftp.rrzn.uni-hannover.de/pub/mirror/tex-archive/macros/latex/contrib/hyperref/doc/manual.html#x1-190005, please take a look on section 5 Acrobat-specific behavior –  May 06 '14 at 16:42
  • @ChristianHupfer If I understand this function correctly, it does precisely what it's intended to do: it will copy the current selection. So in order to make this work, we'd have to define a macro that selects a part of the ActualText automatically. – 1010011010 May 06 '14 at 16:48
  • You mean, something like the buttons in the navigation bar on a beamer slides? But that copy the text "into the clipboard". Do you need some formatting? Or just the text as outputted from pdftotext? – phollox Jul 19 '18 at 15:37

1 Answers1

3

I'm happy to report that it is possible, even if with some limitations:

  • Acrobat only solution (but cross-platform, I think)
  • You need to trust the PDF (e.g. "Acrobat Pro DC > Preferences > Security (Enhanced) > Add Folder Path"), since the app.execMenuItem("Copy"); requires privilege.
  • It's not all that elegant; it flashes a big form at you for a quick moment.

That being said, here's an MWE:

\documentclass{article}

\usepackage{media9}

\begin{document}

\mediabutton[
    jsaction={
        var fld = this.addField("ToCopy", "text", \thepage-1, this.getPageBox({nPage: \thepage-1})); % Creates field named "ToCopy" of type "text" on the current page of the size of the current page
        fld.value = "never gonna give you up..."; % sets the content of the field
        fld.setFocus(); % selects the content of the field
        app.setTimeOut("app.execMenuItem('Copy');", 1); % copies the selection. 1ms is the lowest pause that worked for me
        app.setTimeOut("this.removeField('ToCopy');", 17); % removes the field. 17ms is the lowest pause that worked for me
    }
]{\fbox{\strut Copy to Clipboard without Alert}}

\mediabutton[
    jsaction={
        var fld = this.addField("ToCopy", "text", \thepage-1, this.getPageBox({nPage: \thepage-1}));
        fld.value = "never gonna let you down...";
        fld.setFocus();
        app.alert("Copied to Clipboard!");
        app.execMenuItem("Copy");
        this.removeField("ToCopy");
    }
]{\fbox{\strut Copy to Clipboard with Alert}}

\end{document}

screen recording

  • Why a form that fills the entire page?
    • So that focusing on the form doesn't make the viewer jump around,
    • To make sure that the text to copy fits in the form (a form too small for its contents didn't work well when I tested it).
  • Why the timeout?
    • Without it, the copying command doesn't work (my best guess is that the setFocus command requires a couple of milliseconds to work, and that, for some reason, the execMenuItem("Copy") command is executed before the former is done).
    • I don't know why so much time is required after the copying (i.e. the 17ms (i.e. 16ms after copying) pause for removing the field), while when using an alarm no time between the two commands is needed.
  • Can't this be improved?
    • Probably, but I couldn't find a way around working with a form. Maybe someone more experienced with Acrobat JavaScript can help.

You can actually also include this in a command of your own, as in e.g.

\newcommand{\createbutton}[2]{
\mediabutton[
    jsaction={
        var fld = this.addField("ToCopy", "text", \thepage-1, this.getPageBox({nPage: \thepage-1}));
        fld.value = "#2";
        fld.setFocus();
        app.setTimeOut("app.execMenuItem('Copy');", 1);
        app.setTimeOut("this.removeField('ToCopy');", 17);
    }
]{\fbox{\strut #1}}
}

Now, as noted above, on my machine a pause between some of the commands is required, either via setTimeOut (which makes the function in its argument be executed after the given time has passed), or by making an alert pop up in between.

I believe my trying to minimize the pauses in the setTimeOut approach has a negative impact on reliability (I got it to, for example, not remove the form after some testing), so perhaps a slightly higher number would be more appropriate (also considering that different machines may require higher or lower pauses).

Please note, though, that this attempt was mostly a proof of concept; I doubt this is all that practical in the real world, at least not if the PDF is to be widely distributed. But I'd be happy to be proven wrong, especially by someone improving this answer. All the best!


Further reading:

steve
  • 2,154