DS Server

JavaScript

Topic

A plain HTML page can display documents with the Document Viewer of DS Server, without a framework or an npm package. Unlike the editor script, the viewer script requires an access token already when the page loads it, so the page first requests a token and then loads the script and initializes the viewer with TXDocumentViewer.init(). The last section moves the token request to your server.

Prerequisites

With a trial token instead of your own server, skip the next section, use https://trial.dsserver.io as the service URL and the client ID and secret of the token; see Trial Token.

How the Page Works

The page runs three steps in order:

  1. It requests an access token from <service URL>/oauth/token with the client credentials grant type. DS Server expects the client ID and secret in an HTTP Basic authorization header.
  2. It loads the viewer script from <service URL>/documentviewer/TextControl/GetResource?Resource=minimized.tx-viewer.min.js and appends the token as the access_token query parameter. When OAuth is enabled, DS Server answers a request for the script without a valid token with the status code 401.
  3. When the script is loaded, it calls TXDocumentViewer.init() with the ID of a container element and the viewer settings, including the token. From then on, the global TXDocumentViewer object controls the viewer.

The Angular and React packages of DS Server load the viewer the same way.

Prepare a Security Profile

  1. In the admin portal of DS Server, choose Security Profiles, click + Create new profile, enter a name and click Create.

  2. Copy the Client ID and the Client Secret of the new profile.

  3. Switch on Allow "Client Credentials" grant type and click Done. It is off by default, and the token request of the page needs it.

    The Authorized Redirect URIs list of a security profile and, below it, the Allow Client Credentials grant type switch turned on in green.

A page that contains the client secret shows it to every visitor. Use it for a first test only; the last section removes it.

Create the HTML Page

Create a file named index.html with the following content. Replace the service URL, the client ID and the client secret with your values.

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <title>DS Server Document Viewer</title>
</head>
<body>

  <div id="txViewer" style="width: 1000px; height: 600px;"></div>

  <script>
    const serviceURL = "http://localhost:5000";
    const clientId = "<client ID>";
    const clientSecret = "<client secret>";

    // 1. Request an access token with the client credentials grant type
    fetch(serviceURL + "/oauth/token", {
      method: "POST",
      headers: {
        "Authorization": "Basic " + btoa(clientId + ":" + clientSecret),
        "Content-Type": "application/x-www-form-urlencoded"
      },
      body: "grant_type=client_credentials"
    })
      .then(response => response.json())
      .then(token => initViewer(token.access_token));

    function initViewer(accessToken) {
      // 2. Load the viewer script with the access token
      const script = document.createElement("script");

      script.onload = function () {
        // 3. Initialize the viewer
        TXDocumentViewer.init({
          containerID: "txViewer",
          viewerSettings: {
            basePath: serviceURL + "/documentviewer",
            dock: 1,
            toolbarDocked: true,
            isSelectionActivated: true,
            showThumbnailPane: true,
            userNames: ["user1"],
            documentData: btoa("<strong>Welcome to DS Server</strong>"),
            documentPath: "welcome.html",
            oauthSettings: { accessToken: accessToken }
          }
        });
      };

      script.src = serviceURL +
        "/documentviewer/TextControl/GetResource?Resource=minimized.tx-viewer.min.js&access_token=" +
        encodeURIComponent(accessToken);
      document.head.appendChild(script);
    }
  </script>

</body>
</html>

What the Page Does

  • The div with the ID txViewer is the container of the viewer. It needs an explicit width and height.
  • fetch() posts grant_type=client_credentials to the token endpoint. The answer is a JSON object whose access_token the page passes on.
  • initViewer() adds the viewer script to the page. Its onload handler runs when the script is loaded and the TXDocumentViewer object exists.
  • TXDocumentViewer.init() creates the viewer in the element named by containerID. The viewerSettings are:
SettingDescription
basePathThe service URL of DS Server followed by /documentviewer
dockHow the viewer is docked: 1 fills the container, 0 fills the browser window
toolbarDockedWhether the toolbar is docked or floating
isSelectionActivatedWhether text can be selected and copied
showThumbnailPaneWhether the pane of page thumbnails is visible
userNamesThe names of users who have access to editable regions
documentDataThe document to display as a Base64-encoded string
documentPathThe document name the viewer displays
oauthSettingsThe access token in accessToken

The viewer also accepts signatureSettings, documentLoadSettings and resources, with the same meaning as the attributes of the Angular component.

Open the Page

Serve index.html from your local web server and open it in the browser. The page shows the Document Viewer with its toolbar, the thumbnail pane and a page with the text "Welcome to DS Server".

Load a Document With JavaScript

After init(), TXDocumentViewer.loadDocument() replaces the displayed document. It takes the document as a Base64-encoded string and the document name for the status bar, and returns a promise. Add a button below the container and a function to the script element:

<input type="button" onclick="loadOtherDocument()" value="Load Document" />
function loadOtherDocument() {
  TXDocumentViewer.loadDocument(btoa("<p>Loaded with <strong>JavaScript</strong></p>"), "loaded.html");
}

To display a file from your server, download it first, for example with fetch, and pass its Base64-encoded content. addEventListener registers handlers for viewer events such as documentLoaded and annotationsChanged.

Keep the Client Secret on Your Server

The page doesn't need the client secret if your server requests the token. The ASP.NET Core application in Keep the Client Secret on Your Server of the Document Editor tutorial does this: its /api/token endpoint sends the client credentials to DS Server and returns the token, and it serves the HTML page from its wwwroot folder. Use the same application, save the viewer page as wwwroot/index.html and replace the fetch() call of step 1 and the three constants for the credentials with a request to the endpoint:

const serviceURL = "http://localhost:5000";

// 1. Request an access token from your own server
fetch("/api/token")
  .then(response => response.json())
  .then(token => initViewer(token.access_token));

The initViewer() function stays as it is. Protect the endpoint the way you protect the rest of your application, because it gives a token to anyone who calls it.

Troubleshooting

  • "DS Server is not registered." On a DS Server without a license, the viewer script only writes this message in red at the top of the page, and the browser console shows TXDocumentViewer is not defined. Register the server in the admin portal, as Licensing describes.

    The red text "DS Server is not registered." at the top of a page that should show the Document Viewer.

  • The script request answers 401: the access_token query parameter is missing or the token isn't valid. A token is valid for the number of seconds that expires_in of the token response gives, 3600.

  • The token request answers 400 with unsupported_grant_type: the security profile doesn't allow the client credentials grant type.

Document Editor and Viewer in Troubleshooting covers more problems.

Next Steps