############################################
Viewing and Interrogating PDF in the Browser
############################################

Advanced Publishing can be used view interactive 3D PDF documents in a browser using standard web technologies without the help of any plug-ins.

This section first addresses how to export a PDF file so it could be viewed inside a browser, followed by a chapter on how to customize our web experience.


.. _toc_pdf_features:

PDF Features
============

.. rubric:: No plugin required

- Our technology is written in native HTML/CSS and JavaScript.
- It implements a subset of Acrobat JavaScript API as described in Acrobat 11 SDK.

.. rubric:: Support 3D PDF interactivity

- Other Advanced Publishing features such as BOM Tables, Carousels are fully supported.
- Most common actions from Adobe Acrobat are supported such as "Open a web link", "open a file", "Go to 3D View", "Run a JavaScript"...

.. rubric:: Browser compatibility

The generated document can be viewed using:

- Google Chrome 69+
- Safari 11.1+
- Firefox 60+

More specifically, your browser must be able to support:
- JS ECMA `class` definition and inheritance
- strict mode
- JavaScript proxy feature (get/set)

You may want to check your browser compatibility using `this link <http://kangax.github.io/compat-table/es6/>`__.


.. _toc_pdf_export_function:

Web Export API
==============

To generate web files from a PDF, use the ``A3DRWParamsExportHtmlData`` data structure and call the method ``A3DConvertPDFToWebFormat()``.

.. code-block:: c

   // This snippet is also part of the sample provided in the package
   A3DRWParamsExportHtmlData paramsExportData = A3D_MAKE_DATA(A3DRWParamsExportHtmlData);
   paramsExportData.m_bIncludeMeasurementInformation = A3D_TRUE;
   paramsExportData.m_pcHtmlTemplateName = pc3DTemplateFile;
   paramsExportData.m_eHtmlOutputMode = kA3DWebOnline;
   paramsExportData.m_ePdfOutputFormat = kA3DWebOutPdfFormatXml;
   paramsExportData.m_i3dOutputFormat = kA3DWebOutFormatHtml;
   A3DStatus status = A3DConvertPDFToWebFormat(pcFileName, &paramsExportData, pcOutputDirectory, pcOutputName);

The file ``pc3DTemplateFile`` in this example is a file that will be used as a template for generating HTML files for each 3D annotation in your PDF. It is provided in the Advanced Publishing package.

3 kinds of outputs are available that can be chosen by the variable :member:`A3DRWParamsExportHtmlData.m_eHtmlOutputMode`. Each have their own way to be viewed inside a web browser to fill different needs.

* :enumerator:`kA3DWebOnline`: The solution for client/server integration and request for best performances.
* :enumerator:`kA3DWebOfflineSingleFile`: The easy way to give a PDF exported to someone.
* :enumerator:`kA3DWebOfflineWithDependencies`: Some middle ground between the two before. No need of a client/server integration, can be easily distributed as long as anyone has some files already setup on their device.

2 kinds of outputs are available that can be chosen by the variable :member:`A3DRWParamsExportHtmlData.m_ePdfOutputFormat`. JSon format is a little heavier in disk space but tends to be faster at loading time in the web browser.

* :enumerator:`kA3DWebOutPdfFormatXml`: the PDF structure is generated using an XML format. This is the default value if not explicitly set.
* :enumerator:`kA3DWebOutPdfFormatJson`: the PDF structure is generated using a JSon format.

3 kinds of outputs are available that can be chosen by the variable :member:`A3DRWParamsExportHtmlData.m_i3dOutputFormat`. They are not exclusive and can be added on top of each other with operator ``|``. It allows different stream 3D outputs in one call so that the model can be viewed in different ways.

* ``kA3DWebOutFormatHtml``: Each stream 3D is exported as an HTML file. This is the default value if not explicitly set.
* ``deprecated_kA3DWebOutFormatScs``: Each stream 3D is exported as an SCS file (deprecated workflow).
* ``kA3DWebOutFormatPrc``: Each stream 3D is exported as a PRC file.

.. _toc_output_online:

Client/Server Integration
=========================

In client/server mode (:enumerator:`kA3DWebOnline`), the call to the function delivers one PDF structure file (format is defined by :member:`A3DRWParamsExportHtmlData.m_ePdfOutputFormat`) and one file per 3D stream in your PDF document (format is defined by :member:`A3DRWParamsExportHtmlData.m_i3dOutputFormat`).

The PDF structure file is the entry point of all. It represents your PDF document. The files will be parsed and displayed in the browser by a client web viewer that we provide as part of Advanced Publishing. See the samples directory in the package download: *samples\\data\\publishhtml\\htmlforserver* .

To help test this functionality, we have provided a simple HTTP server that can be launched by clicking on *samples\\data\\publishhtml\\htmlforserver\\exportpdftohtml\\start_server.bat* .

Once the server is launched, open the following URL in your browser: ``localhost:11180/viewer.html?file=sample_DemoDataModel`` . You can load your own 3D PDF converted by updating the sample querystring parameter with the PDF structure file name describing your document without the file extension : ``localhost:11180/viewer.html?file=FilenameWithoutExtension``.

Be sure to properly URL-encode 'FilenameWithoutExtension'. For instance, there are no spaces in a URL, so any space character in your file name must be replaced by "%20" (without the quotes) for a space character. See https://www.w3schools.com/tags/ref_urlencode.asp for more information about URL encoding.

By default, the viewer of a 3D annotation will display a toolbar and a panel will display the model tree and views. You can hide them by adding the following to your querystring:

* ``&modeltree=none`` to hide the panel with the model tree and views.
* ``&toolbar=none`` to hide the toolbar.
* ``&viewNav=show`` to show a floating widget helping the user to navigate from one view to another.

**Example:** ``localhost:11180/viewer.html?file=sample_DemoDataModel&modeltree=none&toolbar=none``

*viewer.html* can load any generated file - to change the file you're viewing, simply change the query string "file=AnotherFilenameWithoutExtension" in the URL with the new file name.

If you want to integrate this viewer into a larger website, note that the folder where *viewer.html* is located must be set as a root for all files in it. This will allow you to drop any set of generated files into the 'PdfContent' folder at any depth in the sub-folders. To view an exported PDF in a sub-folder of 'PdfContent', just change the querystring to "file=SubFolder/FilenameWithoutExtension" in the URL.

Please note, *viewer.html* can be customized to include your own content or logo. If you need to further customize the 3D viewer component, you might consider using HOOPS Communicator or The HOOPS Web platform. Please `contact us <https://pages.techsoft3d.com/connect-with-us>`_ for more information.

.. rubric:: Integrate into an existing website

The sample contains the file `viewer.html` which is the entry point of our demo. The file is readable and a good starting point for those who want to integrate this solution into an existing website.
The file contains a script section that checks some compatibility with web browsers, and load the PDF structure document (which is your PDF export), retrieve the content and call `Hoops.PdfWebViewer.OpenDocumentFromXml(content)` or `Hoops.PdfWebViewer.OpenDocumentFromJson(content)` where `content` is the content loaded as string. Beware to call the correct function in regards of the format of the PDF structure document.

.. rubric:: HTTP Server Configuration

- Use your own one like Apache HTTP, NodeJS, Python...
- The configuration must enable XML/JSON file transfer.
- No specific port/protocol are required.
- All included files are compatible with HTTPS protocol to manage security.

Also, to optimize network bandwidth, it could be good to enable gzip compression for all files contained in PdfContent folder.


.. _toc_output_offline_standalone:

Single HTML File - Standalone
=============================

For single HTML standalone file output (:enumerator:`kA3DWebOfflineSingleFile`), when calling ``A3DConvertPDFToWebFormat``, you should fill the ``A3DRWParamsExportHtmlData`` data structure with new parameters. The call to the function delivers one HTML file that could be read anywhere if you have a compatible browser.

You must create a ``A3DRWHtmlOfflineData`` data structure and set it with the parameter :member:`A3DRWHtmlOfflineData.m_pHtmlOfflineData`. This structure contains two additional fields:

* :member:`A3DRWHtmlOfflineData.m_pcPathToHtmlViewerFile` is mandatory. You must indicate the viewer file to use. This file is the entry point of our web solution and can be found in the sample directory. Please refer to previous section for how to find it.
* :member:`A3DRWHtmlOfflineData.m_uiOptionFlags` is a set of options you may want to enable amongst ``kA3DWebOfflineShow3DToolbar``, ``kA3DWebOfflineShow3DModelView`` and ``kA3DWebOfflineShowViewNavigation``. These options are detailed in the previous section.

One of the main advantages of this mode is to enable offline viewing of the PDF. Additional benefits include, for instance, simplified cache management on mobile devices.

.. code-block:: c

   // This snippet is also part of the sample provided in the package
   A3DRWParamsExportHtmlData paramsExportData = A3D_MAKE_DATA(A3DRWParamsExportHtmlData);
   paramsExportData.m_bIncludeMeasurementInformation = A3D_TRUE;
   paramsExportData.m_pcHtmlTemplateName = pc3DTemplateFile;

   // set the output as monolithic
   paramsExportData.m_eHtmlOutputMode = kA3DWebOfflineSingleFile;

   // fill and set mandatory parameters
   A3DRWHtmlOfflineData offlineData = A3D_MAKE_DATA(A3DRWHtmlOfflineData);
   offlineData.m_pcPathToHtmlViewerFile = viewerFilePath;
   paramsExportData.m_pHtmlOfflineData = &offlineData;

   A3DStatus status = A3DConvertPDFToWebFormat(pcFileName, &paramsExportData, pcOutputDirectory, pcOutputName, kA3DWebOutFormatHtml);


.. rubric:: Android specificities

On Android, the browsers have different security settings. Chrome, for instance, blocks the linking of JavaScript files if the HTML is opened using something else than the file protocol.
Therefore, on Android, you should always have a path starting with ``file:///sdcard/...`` Some file system explorers on Android do not open files using file protocol by default.


.. _toc_output_offline_distributed:

Single HTML File - Distributed
==============================

For this single distributed file output (:enumerator:`kA3DWebOfflineWithDependencies`), you should also fill :member:`A3DRWHtmlOfflineData.m_pHtmlOfflineData` with the same elements.

The changes from a standalone file lie in how the file is read from the browser. This is not a standalone file as it requires JS and CSS folders to be in the same folder as the file. Those folders are part of the sample we deliver in *samples\\data\\publishhtml\\htmlforserver\\exportpdftohtml\\root*.

There are two benefits for using this export:

* The HTML file generated will be slightly shorter than from a standalone file as JS and CSS files won't be part of it.
* The file will also be loaded slightly faster as JS and CSS files could be loaded by the browser in parallel.

However the main downside is, if you distribute this file, the one who reads it should have the *JS* and *CSS* files on their device as well.
