Below, please find the release notes for VirtualViewer v5.0. For questions, please contact us at questions@snowbound.com or by phone at (617) 607-2010.

New User Interface Design

All toolbar icons and VirtualViewer’s main user interface have been updated to a colorful, flat, and modern look. There is no change to the function or placement of any icons, and no changes to configuration. This feature is enabled by default.

Icons are now displayed as an icon font, rather than individual images loaded by URL. This speeds up the loading time of the viewer, especially on highly latent connections, and provides a smoother user experience.

Custom buttons may still be loaded as individual images. To do this, place the image in a web-accessible directory and point to the image path in the iconImage attribute of a button configuration item in user-config/toolbar-config.js. To blend in with VirtualViewer toolbar icons more smoothly, provide a blue version of the image to display when the user hovers over the icon; set additional CSS to display this blue icon in place of the original image when the CSS pseudoselectors :hover and :focus are active.

SnowDoc for VirtualViewer Java

VirtualViewer has significantly improved the performance of docx, xlsx, pptx, and doc files, using the new SnowDoc feature of RasterMaster Java 20.0.

OfficeX files are performance-intensive to lay out, since they generally don’t contain data specifying where pages begin and end, or locations of characters on pages. Previously, VirtualViewer and RasterMaster were redoing that layout work multiple times; with SnowDoc, layout information is cached between calls so the performance-intensive processing only needs to be done once.

The most dramatic change can be seen by loading a long docx file in VirtualViewer and navigating to the last page. Before 5.0, loading the final page of docx document would take significantly longer than loading a beginning page. Now, the loading time is short, and no longer than any other page in the document.

This new feature does not require any updates to configuration or to content handler code. Initialization parameters for OfficeX and doc formats in web.xml will be respected, with the exception of the default page dimensions for xlsx files. In the case of xlsx files, the xlsxWidth and xlsxHeight initialization parameters will be disregarded in 5.0 in favor of the native dimensions of the document.

It is important to note that caching is crucial to the performance improvements of these files. The initial load of a file with SnowDoc takes the most time; VirtualViewer needs to cache these documents to avoid taking that performance hit over and over. If current configuration or content handler code disables use of ehcache in VirtualViewer, consider enabling caching for docx, xlsx, pptx, and doc files.

Load Font Files into VirtualViewer Java

It is now possible to include font files in the VirtualViewer Java war file. Those fonts will be used to render documents, even if the font is not installed on the server environment running VirtualViewer. The largest effects of this new feature are on Office formats. Previously, in order to accommodate uncommon or rarely-used fonts in an Office document, the font would need to be installed on the server running VirtualViewer, or the document might experience problems with text layout. With this feature, specific fonts no longer have to be installed on the entire server.

The effects of loading a font will differ depending on the format of the loaded document, and whether a document is loaded as an SVG or a PNG. For example, a .docx document loaded as an SVG will display with the correct layout, but may not render in the font unless the font is installed on the client machine. A .docx document loaded as a PNG will display with both the correct layout and the correct font rendered into the image.

To enable this feature, simply add a .ttf file to a folder called fonts within the VirtualViewer war. Within the war, there are folders called js and css. Add a folder called fonts as a sibling to these, so the folder structure looks like this:

VirtualViewer war file
--WEB-INF/
--resources/
--js/
--fonts/    <===
--css/

Add .ttf files to the fonts folder:

VirtualViewer war file
--WEB-INF/
--resources/
--js/
--fonts/    
----MyFont-Italic.ttf <===
--css/

Finally, restart VirtualViewer to initialize the new fonts.

Improved Documentation

VirtualViewer API and code documentation will no longer be included in the PDF manual at www.snowbound.com, but will be generated fully by Javadoc and JSDoc utilities. This allows for complete and up-to-date documentation of API and public code.

The new documentation may be found at the VirtualViewer Manuals Page. Some highlights are:

  • VirtualViewer client-side Javascript API documentation, generated by the JSDoc utility

  • VirtualViewer Java Content Handler API documentation, generated by the Javadoc utility

  • A transition guide for upgrading to VirtualViewer version 5.0. This document, written as a technical guide, steps through the process of modifying the content handler and updating interaction with VirtualViewer API

Content Handler Interface Updated (Content Handler Modification Required)

The interface between the content handler and VirtualViewer have been updated to make it easier to use and set up. Many of these changes will require existing content handlers to be updated to work with the new standard.

A detailed guide on transitioning to 5.0 can be found here.

FlexSnapSI to VirtualViewer

A few classes with names containing FlexSnapSI, our old product name, have been updated to VirtualViewer. This includes the new VirtualViewerContentHandlerInterface and VirtualViewerAPIException.

Usable classes organized into packages

All interfaces and classes that are usable by the content handler can now be found in the com.snowbound.common and com.snowbound.contenthandler namespaces, and all classes in those namespaces have a new detailed API documentation on our website. This will make it very easy to find what is needed for your content handler and see what additional tools are available.

Classes in namespaces other than com.snowbound.common and com.snowbound.contenthandler are for internal use by VirtualViewer and may be obfuscated.

Content handler interfaces modularized

VirtualViewer’s interfaces have been refactored to make it easier to separate out the features you want to implement for your content handler. There is now only one required content handler interface, VirtualViewerContentHandlerInterface, which contains every method a content handler must implement. All other interfaces in com.snowbound.contenthandler.interfaces can be added to enable their features or left out without the need to ‘stub out’ methods.

Many of our interfaces for new features were already modular in this fashion, but now more older features like getAvailableDocumentIds and event notification have been modularized in the same way.

Existing content handlers should be updated to make sure they implement all the interfaces they need, or their old methods will not be called by VirtualViewer.

Explicit commands for content handler actions

The content handler method saveDocumentComponents is now expected to only save, not delete, document components such as bookmarks, document notes, and watermarks. There are three new content handler methods–deleteBookmarkContent, deleteNotesContent, and deleteWatermarkContent–to handle deletion.

Previously, saveDocumentComponents was expected to delete a component such as an XML file storing Snowbound bookmark data if it received a null value. Now, saveDocumentComponents is expected to make no changes on receiving a null value for a component. This is crucial, because VirtualViewer will now send a null value for a component if there have been no changes to save. VirtualViewer will call a deleteBookmarkContent, deleteNotesContent, or deleteWatermarkContent to delete all bookmarks, document notes, or watermarks.

With this feature, VirtualViewer is more maintainable in the future, may send smaller amounts of data, and solves a saving problem.

This feature requires content handler updates for VirtualViewer to function, but the content handler may still compile if the updates are not completed.

ERROR_MESSAGE fully replaced by VirtualViewerAPIException

Throwing a VirtualViewerAPIException is now the only way to pass an error to VirtualViewer. The erroring request will be interrupted exception’s message will be logged and may be displayed to the end user.

New Thumbnail Tab for Viewing Annotation Information

A new tab in the thumbnail pane, displayed to the right of the main document pane, lists metadata for the annotations in a document. Each annotation is described by a small block of text containing the type of the annotation, the page that contains it, and its creation and most-recent modification details. This information is updated live as the user creates, deletes, and modifies annotations.

The annotation information tab is disabled by default, and may be turned on by setting the configuration item showAnnotationList in config.js to true.

New and Changed Callbacks

The VirtualViewer callback system is now implemented on top of JQuery custom events. The existing API to set a callback, virtualViewer.setCallback(callbackName, handlerFunction), still has the same signature; now, calling setCallback multiple times will set multiple handler functions to a single callback event. The handler functions will be called synchronously in an arbitrary order. Note that disableTextContextMenu and disablePageManipulationContextMenuOptions, the only callbacks to support a return value from the handler, may still only have one handler function active at a time.

Handler functions can also be removed by a new API, virtualViewer.removeCallback(callbackName, removeVirtualViewerHandlers). Removing a callback by setting its handler function to null or undefined (for instance, virtualViewer.setCallback('rotation', null);) will no longer deactivate the handler function; removeCallback should be used instead.

Using this mechanism for callbacks not only allows for more flexible integrated code, it allows for custom callbacks to be added without overriding VirtualViewer default callbacks. For instance, VirtualViewer code uses callbacks for default behavior after uploading or saving a document as. Removing a callback with the second parameter set to true will remove the default VirtualViewer behavior for such a callback, but otherwise, behavior can now be added while preserving the old.

Callback API

  • virtualViewer.setCallback(callbackName, handlerFunction) adds a callback handler function. The handler function will be called synchronously from VirtualViewer code.
    • callbackName {string} The name of the callback. For instance, pass in "saveAsDocument" to set a handler function called when a document has completed saving as. Callback names and detailed descriptions can be found in the VirtualViewer clientside documentation.
    • handlerFunction {function} This function will be called and given a single argument object. The attributes of the argument object vary from callback to callback. VirtualViewer code will not respect the return value of a handler function except in two cases: the callbacks disablePageManipulationContextMenuOptions and disableTextContextMenu.
    • Returns true if the callback name was found and the handler function was set
  • virtualViewer.removeCallback(callbackName, removeVirtualViewerHandlers) deactivates and removes all handler functions for the given callback name.
    • callbackName {string} The name of the callback. For instance, pass in "saveAsDocument" to remove handlers that would fire when a document has completed saving as. Callback names and detailed descriptions can be found in the VirtualViewer clientside documentation.
    • removeVirtualViewerHandlers {boolean} In some cases, VirtualViewer supplies default handlers to callbacks. Most of the time, these handlers should be left in place to avoid unexpected behavior. However, it may be necessary to turn off default VirtualViewer handlers to improve integration. In this case, set this parameter to true. In all other cases, this parameter may be left out, and only custom callback handler functions will be removed.
    • Returns true if the callback name was found

New Callbacks

  • onShowSelectTextContextMenu will be called from the show event of the menu that appears when right-clicking the document. This menu may contain options to copy or redact text, to perform OCR, or to add highlight annotations. The following parameters will be provided to the callback in the argument object:
    • documentId {String} The ID of the document that the menu appears over

Modified Callbacks

  • onDocumentLoad will be called when the document model has finished loading. Once the document model has been loaded, the viewer considers the document itself to be loaded and begins loading image- and page-specific information. The following parameters will be provided to the callback in the argument object:
    • documentId {String} The ID of the document that has completed loading
  • rotation will be called when a page is rotated. Pages can be rotated to 0, 90, 180, and 270 degrees. When freshly loaded from the server, a page always starts at 0 degrees rotation, even if it was rotated in a previous VirtualViewer session. The following parameters will be provided to the callback in the argument object:
    • documentId {String} The ID of the document whose page was rotated
    • page {number} The 0-based index of the page that was rotated
    • rotatedTo {number} The angle, in degrees, that the page was rotated to, compared to its original zero position
    • rotatedBy {number} The angle, in degrees, that the page was rotated by, from its position before rotation
    • degrees {number} The angle of rotation. This angle will match either rotatedTo or rotatedBy
  • imageLoadCompleted will be called when an image has completed loading. Loading in VirtualViewer can be a complicated process with several fallbacks for faulty images. This callback is called at the end of the process, when an image is completely loaded and is ready to draw. The following parameters will be provided to the callback in the argument object:
    • val {boolean} Whether the image was loaded
    • documentId {string} The ID of the document whose image is loading
    • page {number} The 0-based index of the page that was loaded
  • overlayImageLoadCompleted will be called when an image has completed loading for use as a template overlay. The following parameters will be provided to the callback in the argument object:
    • val {boolean} Whether the image was loaded
    • documentId {string} The ID of the current base document
    • overlayDocumentID {string} The ID of the document that is made transparent and displayed over the base document
  • imageLoadRequested will be called when a request for an image fires off to the server. VirtualViewer uses a buffering system to preload images. The following parameters will be provided to the callback in the argument object:
    • val {boolean} Whether the image was requested
    • documentId {string} The ID of the document whose image is loading
    • page {number} The 0-based index of the page that is being requested

New and Changed Client-side API

  • rotateSelectedPagesBy rotates specified pagees of the current document by 0, 90, 180 or 270 degrees from its current state.
    • pages {number[]} An array of the 0-based page indices that should be rotated.
    • degrees {number} A value of 0, 90, 180 or 270. These values may be negative.
  • closeTab
    • tabId {number string} Either the 0-based index of the tab or the document ID that the tab refers to.
  • removeWatermarkFromPage
    • page {number} The 0-based index of the page that the watermark is removed from. If a page has multiple watermarks, all the watermarks will be removed from that page.
  • hideAnnTagsPopUp
    • hide {boolean} Whether to hide the annotation tag section. If this value is false or undefined, it will not hide the annotation tag section.

API with New Argument Objects

The following API previously took upwards of ten arguments. Parameter lists as long as that are unwieldy and fragile. These functions now take argument objects, with the parameter names as keys and the arguments as the values. Possible attributes of the arguments object are noted here as options.parameterName.

  • saveDocument will save the current document, including annotations and any image manipulations. The most basic call of this function is simply virtualViewer.saveDocument(), which saves the current document as it is. Passing in additional parameters can save documents other than the current (pass in a docId); can save a document as (pass in options.newDocumentId); and in Save As can include or exclude annotations, redactions, pages, and many more aspects of a VirtualViewer document.
    • docId {string} The ID of the document to save. This document should be currently open (though it may not be currently displayed, it should at least be open in a VirtualViewer tab). If not set, the current document will be saved. This is the only parameter not passed in the options object.
    • options {object} An object storing optional parameters. All following parameters should be passed as attributes in this object.
    • options.newDocumentId {string} Set this parameter to save the current document as a new document in the system. If set, this function operates as “save as”. The original document will remain unchanged, and VirtualViewer will ask the content handler to save a new document with a new ID. Several of the following parameters are designed to only affect Save As.
    • options.newDisplayname {string} Set the display name of the new document. This will only be respected if newDocumentId is set.
    • options.burnRedactions {boolean} Set to true to permanently burn redactions into the new document. If redactions are burned in, the underlying image is converted to the redaction’s black box, and underlying text is removed. This is not reversible.
    • options.includeRedactionTags {boolean} Whether or not to include redaction tags. This is only respected if burnRedactions is true.
    • options.includeTextAnnotations {boolean} Used to permanently burn text annotations into the new document.
    • options.includeNonTextAnnotations {boolean} Used to permanently burn non-text annotations into the new document.
    • options.copyAnnotations {boolean} Used to copy annotation layers (including redactions) into the new document.
    • options.includeWatermarks {boolean} Whether to permanently burn watermarks into the new document. If true, copyWatermarks setting is ignored and watermarks are not copied.
    • options.pageRangeType {string} Either “all”, “complex” or “current”. This parameter is only respected in Save As.
    • options.pageRangeValue {string} A range of pages numbers to export. Dashes and commas can be used: for instance, “2-4,7,10”. This will only be respected if pageRangeType is set to “complex”. This parameter is only respected in Save As.
    • options.copyWatermarks {string} Whether to save/copy watermarks alongside the document. Watermarks saved with this parameter will be editable in the future.
    • options.saveAsFormat {string} This can be “Original”, “PDF” or “TIFF”. Note that “Original” may only be used when exporting a document without including annotations, redactions, watermarks, or document notes. Additionally, to export as the original format, pageRangeType must be “all”. This parameter is only respected in Save As.
    • options.skipOverwriteDialog {boolean} If the current document will be overwritten by a save action, VirtualViewer alerts the user with a dialog. Provide true to this parameter to suppress that dialog.
    • options.documentPaneIndex {number} If document compare is open, provide an index to specify whether to save the first or second open document. Provide 0 for the left-hand document and 1 for the right-hand document. This may be helpful if the user has the same document open in both panes.
  • exportDocument will export the current document as a PDF, a TIFF, or the original format, and locally download the resulting file.
    • options {object} The arguments object. All following parameters should be passed as attributes in this object.
    • options.exportFormat {string} Either “Original”, “PDF” or “TIFF”. Note that “Original” may only be used when exporting a document without including annotations, redactions, watermarks, or document notes. Additionally, to export as the original format, pageRangeType must be “all”.
    • options.fileExtension {string} This is based on the exportFormat parameter. If exportFormat is “Original”, then the extension must be the current file extension of the document. If “PDF”, the extension should be “pdf”. If “TIFF”, then “tif”. Importantly, the extension can only be tif, pdf, or the original extension. VV will not convert a document to any format other than PDF, TIFF, or the document’s original format.
    • options.includeTextAnnotations {boolean} Whether or not to include text annotations.
    • options.includeNonTextAnnotations {boolean} Whether or not to include non-text annotations.
    • options.burnRedactions {boolean} Whether or not to burn in redactions. If redactions are burned, the redaction becomes part of the image and any underlying text is removed. It is not reversible.
    • options.includeRedactionTags {boolean} Whether or not to include redaction tags.
    • options.includeDocumentNotes {boolean} Set this to true to append document notes as text pages at the end of the document.
    • options.includeWatermarks {boolean} Set this to include watermarks in the exported document.
    • options.pageRangeType {string} Either “all”, “complex” or “current”. “all” will export all pages; “current” will export just the current page; but “complex” requires the parameter pageRangeValue to be set as well.
    • options.pageRangeValue {string} A range of pages numbers to export. This may look like: “1-2,3,6,7-10”. VV allows commas and dash-separated ranges.
    • Returns true if the export request has successfully been fired off, and a falsey value if not.
  • printDocument will print a document, using the browser’s print dialog.
    • options {object} An object storing optional parameters. All following parameters should be passed as attributes in this object.
    • options.documentId {string} The ID of a document to print. This document must be open in the viewer.
    • options.printToPDF {boolean} If true, a PDF version of the document will be exported to a file. The user will be presented with a save dialog.
    • options.includeAnnotations {boolean} Whether to include annotations on the printed document.
    • options.includeRedactions {boolean} Whether or not to fully redact the printed document.
    • options.includeRedactionTags {boolean} Whether or not to include redaction tags (only used when redactions are applied to the document).
    • options.includeWatermarks {boolean} Whether or not to print with any of the VirtualViewer-generated watermarks currently on the document.
    • options.includeDocumentNotes {boolean} Set this to true to append document notes as text pages at the end of the document.
    • options.pageRangeType {string} Options are “all”, “complex” or “current”. If “complex”, the parameter pageRangeVal must be included; otherwise it will be ignored.
    • options.pageRangeValue {string} A range of pages numbers to print (only used for “complex” pageRangeType). Commas and dashes may be used. For instance, “2-4,7,10-11” would print only pages 2, 3, 4, 7, 10 and 11.
  • emailDocument will email the current document as a PDF, a TIFF, or as the original format. VirtualViewer email requires some server-side configuration.
    • options {object} The arguments object. All following parameters should be passed as attributes in this object.
    • options.format {string} Either “Original”, “PDF” or “TIFF”. The document must be emailed as a .pdf or .tif file if annotations, redactions, watermarks, or document notes are included, and if pageRangeType is any value other than “all”.
    • options.includeTextAnnotations {boolean} Whether or not to include text annotations.
    • options.includeNonTextAnnotations {boolean} Whether or not to include non-text annotations.
    • options.burnRedactions {boolean} Whether or not to burn in redactions. If redactions are burned, the redaction becomes part of the image and any underlying text is removed. It is not reversible.
    • options.includeRedactionTags {boolean} Whether or not to include redaction tags.
    • options.includeDocumentNotes {boolean} Set this to true to append document notes as text pages at the end of the document.
    • options.includeWatermarks {boolean} [] Set this to true if watermarks should appear on the emailed document.
    • options.pageRangeType {string} Either “all”, “complex” or “current”. “all” will email all pages; “current” will email just the current page; but “complex” requires the parameter pageRangeValue to be set as well.
    • options.pageRangeValue {string} A range of pages numbers to export. This may look like: “1-2,3,6,7-10”. VirtualViewer allows commas and dash-separated ranges.
    • options.fromAddress {string} The sender’s email address. The default can be changed in config.js.
    • options.toAddresses {string} A comma-separated list of recipient email addresses. For instance, “myemail@email.com,youremail@email.com”. The default can be changed in config.js.
    • options.ccAddresses {string} A comma-separated list of email addresses to CC. For instance, “myemail@email.com,youremail@email.com”. The default can be changed in config.js.
    • options.bccAddresses {string} A comma-separated list of email addresses to BCC. For instance, “myemail@email.com,youremail@email.com”. The default can be changed in config.js.
    • options.subject {string} The subject line (title) of the email.
    • options.emailBody {string} The message (body) of the email.
    • Returns true if the email request is sent off successfully, and a falsey value if not.

Loading Custom Image Stamps

With VirtualViewer’s image stamp annotations, users can apply a set of small, administrator-defined images to a document. The available images were defined in web.xml or web.config, and provided in VirtualViewer’s resources directory. This method did not allow dynamic adjustment to the list of stamps, and could cause problems on different servers.

Now, the initial list of available image stamps are configured in config.js, and can be modified dynamically by Javascript API. Further, stamps are loaded with a provided URI, rather than assuming a stamp’s presence and naming convention in the resources directory.

New API

Several of the following API take image stamp objects. An image stamp object has four attributes, "url", "stampTitle", "width", and "height". Only "url" and "stampTitle" are required. An example object, from config.example.js, would look like:

{
  stampTitle: "Approved",
  url: "./resources/stamps/Approved.png",
  width: 535,
  height: 293
}
  • clearImageStamps will remove all the stamp options from the Image Rubber Stamp dropdown list in the toolbar.

  • createImageStamp will add a single image stamp to the Image Rubber Stamp dropdown on the toolbar.
    • url {string} The URI of the stamp’s image.
    • stampTitle {string} The displayed title of the stamp. This will appear in the list in the toolbar.
    • options {object} Dimension options for the stamp. The attributes of this object are listed below as options.attribute.
    • options.width {number} The width of the stamp image. If not provided, the native width of the stamp image will be used.
    • options.height {number} The height of the stamp image. If not provided, the native height of the stamp image will be used.
  • createImageStampArray will add a whole array of image stamps to the viewer. The provided stamps will append to the existing list of stamps. A stamp object has mandatory URL and title properties, and optional width and height properties.
    • stampList {array of image stamps} An array of stamp objects, that require “url” and “stampTitle” properties to be valid, as described above.
  • createImageStampArrayFromFunction will initialize the viewer’s list of image stamps. This takes a callback function as a parameter, and calls that function to get the actual list of image stamps that will be used in the viewer.
    • fn {function} This function is called with no parameters. It is expected to return an array of image stamp objects, as described above. The array returned by this function will be used to fill the stamp list on the toolbar.

Configuration

The web.xml initial parameter customImageRubberStamps has been deprecated in favor of the new config.js initialStamps list and its related stamp Javascript API.

The configuration item initialStamps in config.js holds a list of image stamp objects. An image stamp object consists of a display name for a stamp–the "stampTitle" attribute–and the URI of the stamp image in the "url" attribute. Optional attributes "width" and "height" allow for default dimensions other than the stamp image’s native dimensions.

Due to the URI provided to the stamp object, stamp images may be stored in any accessible location. That may still be locally in the resources/stamps directory within VirtualViewer.

Retain Scroll Position Between Documents

The configuration item fitLastBetweenDocuments overrides the default zoom level, and will open a document at the same percentage of zoom as the last-open document. For instance, if a user zooms to 50% on a document open in the first tab, the document in the second tab will also appear at 50% zoom.

Now, there is a new configuration item to do the same with scrolling: positionLastBetweenDocuments. This will etain the scroll position of the previously-open document. So, for instance, the user may scroll document A to the third page, and scroll a little to the right to center a particular form field on the screen. When the user opens document B, it will open scrolled to the third page and a little to the right. This setting works best with fitLastBetweenDocuments enabled, and with documents of the same approximate size.

To enable, set the configuration item positionLastBetweenDocuments to true in config.js.

Fixes and Changes

Content Handler

In addition to the major content hander changes noted above, some minor fixes and changes have been made.

  • Some deprecated and/or unused properties have been removed from ContentHandlerInput and ContentHandlerResult.
  • Event notification properties are now deprecated on ContentHandlerResult. The equivalent properties on ContentHandlerInput should now be used.
  • The annotation permission level constants on VirtualViewerContentHandlerInterface have been deprecated. The new PermissionLevel enum should be used instead.

Improved EhCache Error Handling in VirtualViewer Java

Previously, an incomplete or malformed ehcache.xml document would completely shut down VirtualViewer. Now, VirtualViewer handles and logs the error, and sets the cache that it was trying to configure as a no-op cache.

Miscellaneous

  • Event notification now provides only necessary parameters to the content handler.
  • The PermissionsEntities annotation layer property has been removed. This is not related to annotation permission levels; permission levels remain.
  • Assigning the clientInstanceId with virtualViewer.setClientInstanceId() can now be done in beforeVirtualViewerInit; previously the value would be overwritten on initialization.
  • Boostrap and JQuery external libraries are updated.
  • Default fit and zoom preferences apply properly to newly-loaded documents.
  • Posted messages are no longer caught by a VirtualViewer listener unless they apply to VirtualViewer.
  • The last tab open in the viewer can now be closed, leaving an empty viewer.
  • Only display the annotation tag section in the annotation pop up menu if tags are available.
  • Annotation size “nubs” are now correctly sized for touch and non-touch environments.
  • VirtualViewer Java no longer clutters the server log with irrelevant, non-VirtualViewer messages.
  • vvConfig.useBrowserScaling turns off Pica scaling.
  • The magnifier now displays a small ‘x’ button, so it can be closed directly rather than by clicking on the toolbar button a second time.
  • VirtualViewer Java server code is now obfuscated to further clarify public and private code, improving content handler stability. All public classes should still be available for use. The VirtualViewer 5.0 transition document has more details on public and private classes in 5.0.
  • The JSESSIONID cookie is restored and updated on the VirtualViewer client on each server request.