34

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.

  • Possibly related: tex.stackexchange.com/questions/117792/… – 1010011010 May 1 '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 ;-) – user31729 May 1 '14 at 21:05
  • Which clipboard? And which PDF viewer? – cfr May 4 '14 at 19:34
  • 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 4 '14 at 19:38
  • 1
    @Euryris: Here is the HTML version of the hyperref manual, for example: ftp.rrzn.uni-hannover.de/pub/mirror/tex-archive/macros/latex/…, please take a look on section 5 Acrobat-specific behavior – user31729 May 6 '14 at 16:42
2

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:

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.