Retrieving and setting current user tool style settings from WebViewer

WebViewer Version: 10.12

Do you have an issue with a specific file(s)? No
Can you reproduce using one of our samples or online demos? No
Are you using the WebViewer server? No
Does the issue only happen on certain browsers? No
Is your issue related to a front-end framework? No
Is your issue related to annotations? Yes

Please give a brief summary of your issue:
Retrieving and setting current user tool style settings from WebViewer

Please describe your issue and provide steps to reproduce it:

Good day. We understand the tool settings last configured by the user is saved in a cookie maintained by the WebViewer. By tool settings, we mean the last style configurations set on tool 1, 2, 3, 4 per annotation and other type of user-initiated setups that is saved in said cookie:

Occasionally, our end users clear their browser cookies because of external and unrelated reasons but when they come back to the WebViewer, all their last configured style properties are reset to default.

We are hoping to somehow get these settings from the WebViewer so that we could save them to our datastore. Then upon initializing the WebViewer, we retrieve those settings from our datastore then set it to the WebViewer.

Ideally, we are looking for an event hook where the user is setting up (i.e. choosing colors, stroke, etc like the one in the screenshot) the style and other related things.

Thank you!

Please provide a link to a minimal sample where the issue is reproducible:
N/A

Hello @joserafael.arce,

Thanks for posting on our forum,

If you would like to retrieve the current default stylings of tools, you can do so by accessing the defaults property on the tool. You can find more information in our helpful guide here, which includes code samples for reading and writing to the default style of a tool: Customizing-default-annotation-styles | Apryse Documentation

We do not have an event that is triggered when the user changes these styles in the UI, but one option could be tracking when the popup itself is opened or closed by using the visibilityChanged event. For example:

  instance.UI.addEventListener('visibilityChanged', (event) => {
    if (event.detail.element == 'toolStylePopup' && !event.detail.isVisible) {
      console.log('toolStylePopup closed');
      // get defaults of tools desired here, upload them to database
    }
  });

Then when the viewer is loaded, you can get the presets from the database and overwrite the defaults objects of the relevant tool.

Let us know if this works for you!

Best Regards,
Jacob Romano Carlsen
Web Development Support Engineer
Apryse Software Inc.

Good day! By default stylings of the tool, do you mean each individual tool? For example, I have to get the default style of the Rectangle tool then the Ellipse tool then the Arrow tool etc?

Also, could you also provide in the example code how to get and set the style of each tool?

Thank you!

Hello @joserafael.arce,

Yes, each individual tool has its own default setting for each property (StrokeColor, TextColor, etc.). If the user changes the default setting of a tool, that setting is saved to local storage on the browser. You can actually see the stored defaults in local storage by looking in the application tab of the browser dev tools:

It is worth noting that the name of the setting may be different depending on if you are using IFrame or WebComponent:

To get the style of every tool, you can check the defaults object for each tool like such:

  // get all tools
  const tools = instance.Core.documentViewer.getToolModeMap();
  // for each tool value in the map, output the defaults
  Object.values(tools).forEach(tool => {
    console.log(tool.name, tool.defaults);
  });

You can always filter tools to see if it its default settings exists in the local storage (or in the database). Here’s the MDN docs for localstorage for your convenience: Window: localStorage property - Web APIs | MDN

To set the style of every tool, you can use the setStyles() API. You can find the API doc here: Apryse WebViewer Class: GenericAnnotationCreateTool
A simple example overriding all the tools would look something like this:

  const tools = instance.Core.documentViewer.getToolModeMap();
  Object.values(tools).forEach(tool => {
    tool.setStyles({
        // insert property overrides such as StrokeColor, TextColor, etc. Not all annotation types have the exact same defaults
    });
  });

You can find more code examples here: https://docs.apryse.com/documentation/web/guides/customizing-default-annotation-styles/

Let us know if this works for you!

Best Regards,
Jacob Romano Carlsen
Web Development Support Engineer
Apryse Software Inc.

Hi, Jacob.

Thank you for the information. We’ll try combining the code ideas from 1st and 2nd reply and see if we can achieve real-time saving of tool settings to our datastore.

Thank you very much!

1 Like

Good day @jromanocarlsen

I have recently tried to prototype on our application the code suggestions above. Getting the style defaults seems to be working and I am able to save it to our datastore. Now as for setting the style, I’ve put it under the WebViewer(...).then((instance) => { ... }); but it does not seem to be working.

This is the code I am trying so far (Angular Typescript):

        const savedStyles = this._annotationUserToolData.toolData;

        Object.keys(savedStyles).forEach((toolName) => {
          const tool = instance.Core.documentViewer.getTool(toolName);

          if (tool) {
            console.warn(toolName, savedStyles[toolName]);
            tool.setStyles(savedStyles[toolName]);
          }
        });

this._annotationUserToolData comes from our datastore but basically whatever the tool.defaults is, we just save it to the datastore. For example, this is what this._annotationUserToolData looks like in JSON:

{
	"toolData": {
		"AnnotationCreateRectangle3": {
			"StrokeColor": {
				"R": 255,
				"G": 255,
				"B": 255,
				"A": 1
			},
			"FillColor": {
				"R": 78,
				"G": 125,
				"B": 233,
				"A": 1
			},
			"StrokeThickness": 6,
			"Opacity": 1,
			"StrokeStyle": "solid"
		},
		"AnnotationCreateArrow": {
			"StrokeColor": {
				"R": 246,
				"G": 154,
				"B": 0,
				"A": 1
			},
			"FillColor": {
				"R": 0,
				"G": 0,
				"B": 0,
				"A": 0
			},
			"StrokeThickness": 6,
			"Opacity": 1,
			"StartLineStyle": "None",
			"EndLineStyle": "OpenArrow",
			"StrokeStyle": "solid"
		},
		"AnnotationCreateRectangle": {
			"StrokeColor": {
				"R": 241,
				"G": 160,
				"B": 153,
				"A": 1
			},
			"FillColor": {
				"R": 0,
				"G": 0,
				"B": 0,
				"A": 0
			},
			"StrokeThickness": 1,
			"Opacity": 0.7500407630849503,
			"StrokeStyle": "solid"
		},
		"AnnotationCreateRectangle4": {
			"StrokeColor": {
				"R": 0,
				"G": 0,
				"B": 0,
				"A": 1
			},
			"FillColor": {
				"R": 0,
				"G": 204,
				"B": 99,
				"A": 1
			},
			"StrokeThickness": "5.00",
			"Opacity": 0.3097994456220447,
			"StrokeStyle": "dash,2,2"
		}
	}
}

In the outputted console.warn lines, confirmed that I am getting the style data properties correctly:

But once that’s done and I look at the WebViewer, I see for example Rectangle Tool 1, 3 and 4 looking greyed out:
image

And then once you attempt to edit their styles, the WebViewer crashes with these error in the console:

Hello @joserafael.arce,

Thanks for reaching out.

After reviewing the code it appears you will need to parse any of the styling which requires a Color (such as StrokeColor, TextColor, etc) into a new Color instance.

As a sample code, you can try the following:

Object.keys(savedStyles).forEach((toolName) => {
      console.log('toolName', toolName);
    const tool = instance.Core.documentViewer.getTool(toolName);
      console.log('tool', tool);

    if (tool) {
      console.warn(toolName, savedStyles[toolName]);
      // tool.setStyles(savedStyles[toolName]) may contain properties with an object with a R, G, B, A value. These will need to be converted into a Color object
      const styles = savedStyles[toolName];
      Object.keys(styles).forEach((style) => {
        if (typeof styles[style] === 'object' && style.includes('Color')) {
          styles[style] = new instance.Core.Annotations.Color(styles[style].R, styles[style].G, styles[style].B, styles[style].A);
        }
      });
      tool.setStyles(savedStyles[toolName]);
    }
  });

The code sample is a proof of concept and will not be maintained. Feel free to adjust the code to fit your desired workflow.

When using this code the tools are set accordingly:

Let us know if this works for you!

Best Regards,
Jacob Romano Carlsen
Web Development Support Engineer
Apryse Software Inc.

Good day @jromanocarlsen

Thank you very much for your response. I confirmed that with your code change, the prototype is successfully functioning. I would like to ask if there are other “color” properties besides StrokeColor and FillColor to be aware of? Or is using the style.includes('Color') check sufficient to handle all the tools now and in future versions?

Thank you!
Rafael Arce

Hello @joserafael.arce,

Properties can vary depending on the annotation type. You can find a full list of properties for each annotation on our API docs, such as the Rectangle Annotation here: https://docs.apryse.com/api/web/Core.Annotations.RectangleAnnotation.html#main

Another example of an annotation type with other color properties would be the FreeText annotation, which you can find here: https://docs.apryse.com/api/web/Core.Annotations.FreeTextAnnotation.html#main

Feel free to also keep an eye on our changelogs for any added features: https://docs.apryse.com/web/changelog/

Hope this helps!

Best Regards,
Jacob Romano Carlsen
Web Development Support Engineer
Apryse Software Inc.