Technical FAQs

Question

By default, in the PrizmDoc Viewer, links are highlighted and underlined in blue. To follow links within a document, the user needs to click the link, wait for the floating popup to appear showing the link’s target URL, and then click that to actually follow the link. Is there a way to make this a single-click process and skip the floating popup?

Answer

The desired one-click functionality can be achieved by modifying the viewer.js source file:

Inspect around line ~9457; you’ll find the following else if block:

    } else if (ev.targetType === "documentHyperlink") {
        hyperlinkMenuHandler(ev, "view");
    }

This line of code executes when the user clicks on a link displayed within the Viewer. The call to hyperlinkMenuHandler is responsible for displaying the floating popup. If you’d like to immediately open the link in a new window/tab instead, replace the contents of the “if else” block with a call to window.open:

    } else if (ev.targetType === "documentHyperlink") {
        window.open(ev.hyperlink.href, '_blank');
    }

This will allow hyperlinks that appear in the Viewer to be followed in a new window/tab with a single-click.

Question

Why am I seeing requests sent through pcc.ashx when they shouldn’t be?

Answer

The default option for the imageHandlerUrl is pcc.ashx so if, for instance, you misspelled imageHandlerUrl or in some other way do not have the setting properly implemented, you will see requests sent through pcc.ashx.

This has been seen when trying to set up the pas-service reverse proxy redirect for Prizm Application Services (PAS).

A sample implementation of this setting can be found in the viewer.js around line 288.

options.imageHandlerUrl = options.imageHandlerUrl || "../pcc.ashx";
Question

When using the PrizmDoc samples, the sample documents included are taking close to 1 minute to load in the viewer. The same also happens when uploading files into the sample.

The server processes are showing minimal impact on CPU and memory. However, the hard drive was spiking to 100% utilization sporadically.

Answer

We have found that Windows Defender with enabled Real-Time scanning can significantly impact performance. Once Real-Time scanning was disabled, we found this issue to be immediately resolved.

To disable Windows Defender, you can do the following:

  1. Right-click on the Windows Logo in the lower left-hand corner and select Control Panel.
  2. Select Windows Defender and then select Settings.
  3. Under the Real-Time protection section, slide the switch to Off.
Question

In PrizmDoc, my text annotation won’t fit the bounding box as if there is padding on the text. How can I fix this?

Answer

Check to see if there’s any custom styling to the body tags. If you have any sort of padding applied to the “body” element in the CSS, it may affect the text annotation, which is a foreign object with a body tag in it.

Question

What is the absolute bare minimum I need to use PrizmDoc Cloud?

Answer

This will allow you to load a document via a URL using PrizmDoc Cloud. Just include your PrizmDoc Cloud API key in the POST request headers.

Please note: This is purely intended as a proof-of-concept. You should never include your API key in your client-side Javascript.

<!DOCTYPE html>

<html lang="en">
<head>
    <!-- Metadata -->
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="description" content="" />

    <!-- Title -->
    <title>AccuSample</title>

    <!-- Libraries -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.0/normalize.min.css">

    <!-- PrizmDoc CSS -->
    <link rel="stylesheet" href="https://raw.githack.com/Accusoft/hello-prizmdoc-viewer-with-nodejs-and-html/master/public/viewer-assets/css/viewercontrol.css">
    <link rel="stylesheet" href="https://raw.githack.com/Accusoft/hello-prizmdoc-viewer-with-nodejs-and-html/master/public/viewer-assets/css/viewer.css">

    <!-- Inline Stylesheet -->
    <style></style>

</head>
<body>

    <!-- #viewer -->
    <div id="viewer" class="pccv pcc-full-screen"></div>

    <!-- Libraries -->
    <script src="https://raw.githack.com/Accusoft/hello-prizmdoc-viewer-with-nodejs-and-html/master/public/viewer-assets/js/jquery-3.4.1.min.js"></script>
    <script src="https://raw.githack.com/Accusoft/hello-prizmdoc-viewer-with-nodejs-and-html/master/public/viewer-assets/js/jquery.hotkeys.min.js"></script>
    <script src="https://raw.githack.com/Accusoft/hello-prizmdoc-viewer-with-nodejs-and-html/master/public/viewer-assets/js/underscore.min.js"></script>

    <!-- PrizmDoc JS -->
    <script src="https://raw.githack.com/Accusoft/hello-prizmdoc-viewer-with-nodejs-and-html/master/public/viewer-assets/js/viewercontrol.js"></script>
    <script src="https://raw.githack.com/Accusoft/hello-prizmdoc-viewer-with-nodejs-and-html/master/public/viewer-assets/js/viewer.js"></script>
    <script src="https://raw.githack.com/Accusoft/hello-prizmdoc-viewer-with-nodejs-and-html/master/public/viewer-assets/js/viewerCustomizations.js"></script>

    <!-- Inline Script -->
    <script>

        let viewingSessionId;
        let viewerControl;

        $(document).ready(function() {
            $.ajax({
                "type": "POST",
                "url": "https://api.accusoft.com/prizmdoc/ViewingSession",
                "headers": {
                    "acs-api-key": "4lTamQVZmrkqZhH8cZhdu7L0xyhUa3gorcaCFQpA_zmuowZs4zoF39V4IckpnVW_"
                },
                "data": JSON.stringify({
                    "source": {
                        "type": "url",
                        "url": "https://www.usability.gov/sites/default/files/creating-wireframes.pdf"
                    }
                })
            }).done(function(response) {
                PCCViewer.Ajax.setHeaders({
                    "acs-api-key": "4lTamQVZmrkqZhH8cZhdu7L0xyhUa3gorcaCFQpA_zmuowZs4zoF39V4IckpnVW_"
                });

                viewingSessionId = response["viewingSessionId"];

                // Initialize viewer
                viewerControl = $("#viewer").pccViewer({ 
                    "documentID": viewingSessionId,
                    "imageHandlerUrl": "https://api.accusoft.com/prizmdoc",
                    "language": viewerCustomizations.languages["en-US"],
                    "template": viewerCustomizations.template,
                    "icons": viewerCustomizations.icons,
                    "annotationsMode": "LayeredAnnotations"
                }).viewerControl;

                viewerControl.on("ViewerReady", function() {
                    console.log("Ready!");
                });
            });
        });

    </script>

</body>
</html>
Question

Can I host multiple PrizmDoc viewers on a single page?

Answer

It is possible to host multiple viewers on a single page. The following example leverages Bootstrap’s tab implementation:

<!DOCTYPE html>

<html lang="en">
<head>
    <!-- Metadata -->
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
    <meta name="description" content="" />

    <!-- Title -->
    <title>AccuSample</title>

    <!-- Libraries -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/7.0.0/normalize.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0/css/bootstrap.min.css">

    <!-- PrizmCSS -->
    <link rel="stylesheet" href="https://pcc-demos.accusoft.com/static/viewer-latest/css/viewercontrol.css">
    <link rel="stylesheet" href="https://pcc-demos.accusoft.com/static/viewer-latest/css/viewer.css">

    <!-- Inline Stylesheet -->
    <style>
        body {
            overflow-y: hidden;
        }
        #viewer1, #viewer2 {
            height: calc(100vh - 3em);
            width: 100%;
        }
    </style>

</head>
<body>
    <!-- #main -->
    <main class="container">
        <ul class="nav nav-tabs" role="tablist">
            <li class="nav-item">
                <a class="nav-link active" id="viewer1-tab" data-toggle="tab" href="#viewer1">Viewer 1</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" id="viewer2-tab" data-toggle="tab" href="#viewer2">Viewer 2</a>
            </li>
        </ul>

        <div class="tab-content">
            <div class="tab-pane fade show active" id="viewer1" role="tabpanel">
                <div id="viewer1">
                </div>
            </div>
            <div class="tab-pane fade" id="viewer2" role="tabpanel">
                <div id="viewer2">
                </div>
            </div>
        </div>
    </main>

    <!-- Libraries -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.1/umd/popper.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0/js/bootstrap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

    <!-- PrizmJS -->
    <script src="https://api.accusoft.com/v1/docstore/viewer/assets/classic/bundle.js"></script>
    <script src="https://pcc-demos.accusoft.com/static/viewer-latest/js/jquery.hotkeys.min.js"></script>
    <script src="https://pcc-demos.accusoft.com/static/viewer-latest/js/viewercontrol.js"></script>
    <script src="https://pcc-demos.accusoft.com/static/viewer-latest/js/viewer.js"></script>

    <!-- Inline Script -->
    <script>
        var viewingSessionId1;
        var viewerControl1;
        var viewingSessionId2;
        var viewerControl2;

        $(document).ready(function() {
            $.ajax({
                "type": "post",
                "url": "https://api.accusoft.com/PAS/V1/ViewingSession",
                "headers": {
                    "acs-api-key": ""
                },
                "data": JSON.stringify({
                    "source": {
                        "type": "url",
                        "url": ""
                    }
                })
            }).done(function(response) {
                viewingSessionId1 = response["viewingSessionId"];

                // Initialize viewer
                viewerControl1 = $("#viewer1").pccViewer({ 
                    documentID: viewingSessionId1,
                    imageHandlerUrl: "https://api.accusoft.com/v2/viewers/proxy",
                    language: languageItems,
                    template: htmlTemplates
                }).viewerControl;
            });

            $.ajax({
                "type": "post",
                "url": "https://api.accusoft.com/PAS/V1/ViewingSession",
                "headers": {
                    "acs-api-key": ""
                },
                "data": JSON.stringify({
                    "source": {
                        "type": "url",
                        "url": ""
                    }
                })
            }).done(function(response) {
                viewingSessionId2 = response["viewingSessionId"];

                // Initialize viewer
                viewerControl2 = $("#viewer2").pccViewer({ 
                    documentID: viewingSessionId2,
                    imageHandlerUrl: "https://api.accusoft.com/v2/viewers/proxy",
                    language: languageItems,
                    template: htmlTemplates
                }).viewerControl;
            });
        });
    </script>
</body>
</html>
Question

When specifying the Amazon AWS access keys or IAM Role associated to the S3 bucket, what are the minimum necessary rights that I need to have for licensing to function?

Answer

The security policy associated to the IAM Role or User who has access to the S3 bucket needs to contain specific S3 bucket rights below:

listObjects

  • AWS S3 listObjects docs
  • Requires s3:ListBucket

putObject

  • AWS S3 putObject docs
  • Requires s3:PutObject

deleteObjects

  • AWS S3 deleteObjects docs
  • Requires s3:DeleteObject
Question

Why do I get a “File Format Unrecognized” exception when trying to load a PDF document in ImageGear .NET?

Answer

You will need to set up your project to include PDF support if you want to work with PDF documents. Add a reference to ImageGear24.Formats.Pdf (if you’re using another version of ImageGear, make sure you’re adding the correct reference). Add the following line of code where you specify other resources:

using ImageGear.Formats.PDF;

Add the following lines of code before you begin working with PDFs:

ImGearFileFormats.Filters.Insert(0, ImGearPDF.CreatePDFFormat());
ImGearPDF.Initialize();

The documentation page linked here shows how to add PDF support to a project.

Question

How do I change the default directory of the SmartZone folder from %TEMP% to something else?

Answer

As SmartZone runs, it will create a folder in the %TEMP% directory containing a few files that the engine needs to run. If you want to change this location, you can do that by creating an INI file in the same directory as the executable that runs your application. You must name that INI file smartzoneengineloader.ini. The contents of smartzoneengineloader.ini should look like this:

[smartzoneengineloader] tempdir = C:\Your\Path\Here\
Question

How do I remove XMP Data from my image using ImageGear .NET?

Answer

When removing XMP data in ImageGear, the simplest way to do this is to set the XMP Metadata node to null, like so:

ImGearSimplifiedMetadata.Initialize(); 
doc.Metadata.XMP = new ImGearXMPMetadataRoot();

Or, you can traverse through the metadata tree and remove each node from the tree:

// Example code. Not thoroughly tested
private static void RemoveXmp(ImGearMetadataTree tree)
{
ArrayList toRemove = new ArrayList();
foreach (ImGearMetadataNode node in tree.Children)
{
    if (node is ImGearMetadataTree)
        RemoveXmp((ImGearMetadataTree)node);

    if (node.Format != ImGearMetadataFormats.XMP)
        continue;

    toRemove.Add(node);
}

foreach (ImGearMetadataNode node in toRemove)
    tree.Children.Remove(node);
}
Question

When viewing documents within the PrizmDoc Viewer using a particular browser, we are seeing garbage text. Viewing the same document with other browsers shows the text properly. What could be causing this to occur?

Answer

There are two possible causes for this in Internet Explorer 11 and you can check the settings below to potentially fix the issue:

In Internet Explorer 11 settings, ensure the Font Download option is enabled:

  1. Click on Internet Options.
  2. Select the Security Tab.
  3. Under Local Intranet zone, select Custom Level.
  4. Under Downloads, set Font download to Enabled.

Disable the “Turn off Data URI” support setting:

  1. Click Start, type gpedit.msc in the Start Search box, and then press Enter.
  2. In the navigation pane of the Local Group Policy Editor window, expand Computer Configuration > Administrative Templates > Windows Components > Internet Explorer > Security Features.
  3. In the right pane, double-click Turn Off Data URI support.
  4. Select Disable, click Apply, and then click OK.
  5. Go back to the navigation pane of the Local Group Policy Editor window, expand User Configuration > Administrative Templates > Windows Components > Internet Explorer > Security Features.
  6. Repeat steps 3 and step 4 above.

In Internet Explorer 11 settings, ensure Ignore font styles specified in webpages is not checked.

  1. Click on Internet Options.
  2. Select the General Tab.
  3. Click on Accessibility button.
  4. Un-check Ignore font styles specified in webpages.

In Chrome this is a bug that was found about 3 years ago and fixed in Chrome Canary, but not in Chrome Stable at the time:

https://productforums.google.com/forum/#!msg/chrome/rpmz56gnFKc/nPLtsbYZBwAJ

This may be why Chrome is having problems. Consider either updating Chrome Stable to the latest version or testing in Chrome Canary to see if that fixes the garbage character issues with that browser.


In Mozilla Firefox there is a setting you can enable which could resolve this problem in that browser:

  1. Go to Options/Preferences > General: Fonts & Colors > Advanced and select Allow pages to choose their own fonts (instead of My selections above).
Question

With PrizmDoc, how can I hide a predefined search if there are no results?

Answer

The predefined search option does not support that functionality, but you can instead perform a server-side search, and then activate the search panel if there are results to show:

var viewer;
var viewingSessionId = <%= viewingSessionId %>;

var fixedSearchTerm = "the";
var pasUrl = "/pas";

var viewerReady = false;
var searchReady = false;
var searchDisplayed = false;

function displaySearchIfNeeded() {
    // The search is only displayed once the viewer is ready, and once our preliminary server-side search comes back positive.
    if (viewerReady && searchReady && !searchDisplayed) {
        searchDisplayed = true;

        $("[data-pcc-search=\"input\"]").val(fixedSearchTerm);
        $("[data-pcc-search=\"submit\"]").click();
    }
}

function sendSearchPost() {
    $.ajax({
        "method": "POST",
        "url": pasUrl + "/v2/viewingSessions/" + viewingSessionId + "/searchTasks",
        "data": JSON.stringify({
            "input": {
                "searchTerms": [
                    {
                        "type": "simple",
                        "pattern": fixedSearchTerm,
                        "caseSensitive": false,
                        "termId": "0"
                    }
                ]
            }
        }),
        "contentType": "application/json",
        "success": function(response) {
            $.ajax({
                "url": pasUrl + "/v2/searchTasks/" + response["processId"] + "/results?limit=1",
                "success": function(response) {
                    if (response.results.length !== 0) {
                        searchReady = true;

                        displaySearchIfNeeded();
                    }
                },
            });
        },
        "error": function(jqXHR, textStatus, errorThrown) {
            if (jqXHR.status === 480) {
                setTimeout(sendSearchPost, 2000);
            }
        }
    });
};

setTimeout(sendSearchPost, 500);

$(document).ready(function() {
    // Since we are no longer restricted to a predefined search, we can load the viewer ASAP.
    viewer = $("#viewer").pccViewer({
        "documentID": viewingSessionId,
        "imageHandlerUrl": "/pas",
        "language": viewerCustomizations.languages["en-US"],
        "template": viewerCustomizations.template,
        "icons": viewerCustomizations.icons
    });

    viewer.viewerControl.on("ViewerReady", function(event) {
        viewerReady = true;

        displaySearchIfNeeded();
    });
});