\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}