[Tex/LaTex] Copy to clipboard feature in PDF output

acrobatcopy/pastejavascript

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.

Best Answer

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: