\documentclass[a4paper]{article} \usepackage[english]{babel} \usepackage{listings} \usepackage{javascripthttp} \usepackage{hyperref} \begin{document} \setlength{\parindent}{0pt} \setlength{\parskip}{5pt plus 2pt minus 1pt} \title{JavascriptHttp Documentation \& Manual} \author{Cedric Zwahlen \\ \texttt{cedric-vince@gmx.ch}} \maketitle \tableofcontents \newpage \section{Introduction} {\noindent The aim of this package is to make it as easy as possible to \textit{get} or \textit{post} data from or to REST-API's from within a PDF document. Specifically, this package adds LaTeX commands to create highly customisable buttons with which to fetch, transform and display data from a remote location. \\ These features make use of Javascript, which means a PDF using them \textbf{only works with Adobe Acrobat Pro}. Other PDF viewers (including Acrobat Reader) may still display the interactive elements, but will not be able to run Javascript or access the internet. } \section{Prerequisites} {\noindent Acrobat Pro blocks Networking code by default. Because this package requires it, you must first change some settings.\\ Navigate to \textbf{Preferences\textgreater Security (Enhanced)}. Then, add the path to your PDF via the 'Add Folder Path' button. The javascripthttp package depends on the acrotex macro. More information about acrotex can be found here: \url{https://www.ctan.org/pkg/acrotex} } \section{Textfields} \begin{description} \item[\textbackslash SimpleTextField] { \sffamily \{$\langle$unique identifier$\rangle$\} } \end{description} {\noindent Adds a writable textfield to the document. $\langle$unique identifier$\rangle$ should not be reused by other Simple elements. It must not contain an underscore '\_'. Use this specifier to obtain a reference to the textfield in Javascript or as a $\langle$target$\rangle$ in other Simple elements. } \subsection{Readonly} \begin{description} \item[\textbackslash SimpleTextFieldReadonly] { \sffamily \{$\langle$unique identifier$\rangle$\} } \end{description} \begin{description} \item[\textbackslash SimpleTextFieldShortReadonly] { \sffamily \{$\langle$unique identifier$\rangle$\} } \end{description} \begin{description} \item[\textbackslash SimpleTextFieldMultilineReadonly] { \sffamily \{$\langle$unique identifier$\rangle$\} } \end{description} {\noindent A readonly textfield does not accept user input. It's content can only be changed through Javascript code. } \newpage \section{GET Requests} \hypertarget{get_1}{\subsection{The Simple Way}} \begin{description} \item[\textbackslash SimpleGET] { \sffamily \{$\langle$unique identifier$\rangle$\} \{$\langle$label$\rangle$\} \{$\langle$URL$\rangle$\} \{$\langle$keypath$\rangle$\} \lbrack$\langle$target$\rangle$\rbrack } \end{description} {\noindent If you want to get information from the internet, use this command.\\ This command adds a button that contains the text specified in $\langle$label$\rangle$.\\ The $\langle$unique identifier$\rangle$ should not be reused by other Simple elements. It must not contain an underscore '\_'. This identifier can be used to obtain a reference to the button in Javascript.\\ $\langle$URL$\rangle$ refers to the address of the REST API endpoint. Note that if you pass a string, you must surround it with either ' or ", just like you would with Javascript strings.\\ If the endpoint in question returns a json file, use $\langle$keypath$\rangle$ to refer to the property you would like to display in a textfield. As an example, consider the following JSON object: \begin{lstlisting} { "abc" : [ { "xyz" : "Starfruit" }, { "xyz" : "Mango" } ] } \end{lstlisting} To display the value "Mango", pass 'abc.1.xyz' (including ') as the keypath.\\ Finally, $\langle$target$\rangle$ specifies the name of the textfield, in which to display the value of the property specified in $\langle$keypath$\rangle$. If no such textfield exists, then nothing is displayed. This parameter is optional.\\ } \subsection{URL Interpolation} {\noindent You can use URL interpolation to insert contents of a textfield into your URL. To do this, wrap the $\langle$unique identifier$\rangle$ of a textfield in curly braces where you want to insert its content in the URL. An example: \begin{lstlisting} https://api.datamuse.com/words?rel_rhy={textfield1} \end{lstlisting} \subsection{Using Lambdas} \subsubsection{URL Argument} {\noindent In some cases, $\langle$URL$\rangle$ interpolation might not be enough to produce the URL that you need. If this is the case, you can also pass a Javascript lambda (a.k.a arrow function) as the parameter. This enables a great deal of freedom, but might present a security risk if you do not know the origin of a document.\\ If you pass a lambda as the $\langle$URL$\rangle$ parameter, the function must return the final URL as a string. The lambda does not take any arguments.\\ You can obtain a valid reference to 'this' in the lambdas context. Refer to \url{https://opensource.adobe.com/dc-acrobat-sdk-docs/library/jsapiref/index.html} for the Acrobat Javascript API Reference.\\ } \subsubsection{Keypath Argument} {\noindent If you need to perform additional operations on received data, you can pass a Javascript lambda as the $\langle$keypath$\rangle$ parameter instead of a string. Allowing anyone to execute arbitrary code might introduce a security risk, so documents from unknown origins should not be trusted. The lambda takes two arguments; the data received from remote as a Javascript object, and a reference to 'this'. If your lambda returns a string, it will be displayed in the field specified by $\langle$target$\rangle$.\\ Consider the below example. A lambda is used to get a list of holidays from \url{https://date.nager.at/api/v3/publicholidays/2023/CH}, and then pick one at random.\\} \begin{lstlisting} (json,doc) => { // json is a top level array const x = Math.floor(Math.random() * json.length); // get localName from element x const h = doc.extractKeypath(json,x + '.localName',doc); return h; } \end{lstlisting} \section{POST Requests} \begin{description} \item[\textbackslash SimplePOST] { \sffamily \{$\langle$id$\rangle$\} \{$\langle$label$\rangle$\} \{$\langle$URL$\rangle$\} \{$\langle$keypath$\rangle$\} \{$\langle$factory$\rangle$\} \{$\langle$errors$\rangle$\} \lbrack$\langle$target$\rangle$\rbrack } \end{description} {\noindent If you need to post information to the internet, then use this command. The first four parameters of the \textbf{\textbackslash SimplePOST} command work identically to the \textbf{\textbackslash SimpleGET} command. Refer to \hyperlink{get_1}{GET Requests} for more information.\\ The $\langle$factory$\rangle$ parameter takes a lambda with no arguments to construct the body of your post request. It must return a Javascript object.\\ If you want to display custom error messages in case an operation fails, you can pass a Javascript object specifying an error message for a given HTML error code, an example: \begin{lstlisting} { "400": "error 400", "300": "error 300" , "500" : "error 500"} \end{lstlisting} If you do not want to display any custom error messages, simply pass \{\} – an empty object.\\} \section{Generic Button} \begin{description} \item[\textbackslash SimpleClosure] { \sffamily \{$\langle$id$\rangle$\} \{$\langle$label$\rangle$\} \{$\langle$closure$\rangle$\} } \end{description} {\noindent Also provided as part of this package is a button, that simply takes a lambda. This button can be used to provide other functionality to tie various components together.} \section{Error Handling} {\noindent Any errors that occur while posting or getting will be displayed in an alert box by default. If you do not want this, you can use the command \textbf{\textbackslash ErrorField\{\}}.\\ This command adds a Readonly Textfield with the $\langle$unique identifier$\rangle$ 'errorField'. If an error field exists in your document, any HTTP errors that occur will be silenced, and their error message displayed in the error field.} \end{document}