Tip of the day – my Copy Link Location plugin

There are some questions I get asked a lot by customers, colleagues and people I meet at conferences. One of them is why there isn’t an easy way to copy links detected in Notes documents using LiveText to the clipboard. And I must admit that it is odd. To remedy I’ve actually developed a plugin that installs into Notes 8 to add an action item to links in Notes documents. After installing the plugin an action to the Copy Link Location to the clipboard is added to all links in the Notes client.

The plugin really highlights the power of Notes, LiveText and the plugin architecture in Notes. As you will probably recall – plugins are fun!!!

Besides that a right-click context menu is also added when right-clicking Notes documents to copy the Notes link (notes://) to the clipboard. It’s all part of the same package.

To see how to install etc. head over to my Notes 8 Utils page.

I see this so much that I thought I would repost the solution

I see so many people in Lotus Notes copy/pasting addresses to calculate distances for reimbursements, claiming time etc. and wonder why they do not find an easier way. Such as using a widget in Lotus Notes. A while back I created a widget to let you simply select the destination address and then do the route calculation using Google Maps.

But is does more than that. As a route calculation needs a starting address and a destination address (and it’s hard for me to know the address you would like to use as the starting address) the widget has a component that lets you generate new widgets based on a starting address that you specify. I think it’s pretty clever. And it gets better – the component that generates the widgets is an XPage… 🙂

The post, and link to the widget, may be found in my Google Maps Widget Generator – come grab your own! post.

AbcWidget is trying to be downgraded to a lower installation scope. Reinstallation of this item will not be permitted.

When trying to update a plugin (feature) using a widget the installation failed and I got the below message.

<widget name> is trying to be downgraded to a lower installation
scope. Reinstallation of this item will not be permitted.

I wondered what it meant as I didn’t really understabd the “installation scope” thing so I asked IBM and here’s the answer I got from Doug MacDonald. Very useful and nicely explains why the installation failed.

When you install a widget, it is assign a scope. The scopes have a heirarchy.

  1. If the widget was installed from the corporate catalog using a category of widgets, the scope is catalog.push.
  2. If the widget was installed from the corporate catalog using drag and drop, the scope is user.catalog.
  3. If the widget was installed from a location other than the corporate catalog, the scope is user.import.

You cannot move down the scope hierarchy. For example:

  • Not allowed: If you install a widget from the corporate catalog using a category of widgets and then you try to drag and drop the same widget.
  • Not allowed: If you install a widget from the corporate catalog using drag and drop and then you try to drag and drop the same widget from a file on the file system.

You can move up in scope. For example:

  • Allowed: If you install a widget from the corporate catalog using drag and drop and then you install the same widget from the corporate catalog using a category of widgets.
  • Allowed: If you install a widget by drag and drop from the file system and then install the same widget from the corporate catalog using drag and drop.

New functionality was added in Notes 8.5.1 to make MyWidgets more dynamic

In Lotus Notes 8.5.1 a small, but very useful, addition was made made to the MyWidgets funtionality. From Notes 8.5.1 the preferences that you specify for your widgets may be computed by the platform instead of being mapped to something you specify via LiveText or text selection. Below is a small snippet from an extension.ml file showing how a value is normally mapped to a parameter (in this case “Mikkel Flindt Heisterberg” is mapped to the “name” parameter).

<preference name="name">
<value>Mikkel Flindt Heisterberg</value>
<displayName>name</displayName>
<enumValues/>
<enumDisplayValues/>
<datatype></datatype>
<isEnum>false</isEnum>
<isRequired>true</isRequired>
<isHidden>false</isHidden>
</preference>

So what if you want to use the current username or the current date? Well up to now you were at a loss or you had to incorporate the functionality into the service you linked to. But since this isn’t always possible IBM added the option of specifying it in the widget itself.

The way to do it is by using a “name” or “date” command in place of the static text (“Mikkel Flindt Heisterberg” in the example above). The syntax is as follows:

${command:parameter}

The following two commands are available:

  • name
  • date

As you might be to format the date or specify the part of the username you need (common name, organization etc.) you use “parameter” part to further instruct the command. Below is some documentation on each of the commands.

  • ${name:nameType}
    For example: ${name:cn}/${name:ou}/${name:o} will resolve to “CommonName/OrganizationlUnit/Organization.” For example: ${name:dn} will resolve to the user’s full distinguished name.
  • ${date:dateformat}
    For example: ${date:yyyy MM DD} will resolve to the current date (in this example “2009 03 20”). The “dateFormat” should be a valid Java date format string.

Using the “name” command the above XML snippet becomes:

<preference name="name">
<value>${name:cn}</value>
<displayName>name</displayName>
<enumValues/>
<enumDisplayValues/>
<datatype></datatype>
<isEnum>false</isEnum>
<isRequired>true</isRequired>
<isHidden>false</isHidden>
</preference>

Information is available in the infocenter (Using a widget property to filter a current user name or date)

How to extend Notes 8: using LiveText with capture groups

I get so many question on how to extend Notes 8 that I finally decided to create a series of blog posts on how to do it. All the posts in the series may be found under the extending_notes8 tag. In this post you’ll need familiarity with how MyWidgets and LiveText works. A basic understanding of regular expressions would be beneficial as well.

This post will set the stage for the next post on how to add Java actions that use LiveText recognizers that contain capture groups. No Java code or Eclipse extension point stuff in this post.

Let me start by explaining what capture groups are. As you probably know you use regular expressions to search for text occurrences when using LiveText. In short a regular expression is a text pattern to search for in a block of text. Regular expressions can be hard to grasp at first but once you “have it” they will become an invaluable tool in your arsenal.

A regular expression can range from the simple to the extremely complex. A simple regular expression to find a product number like OTGC-5431 could look like this one:

[A-Z]{4}-d{4}

This regular expression tells the regular expression engine to search for 4 consecutive, uppercase, letters ([A-Z]{4}) followed by a hyphen (-) followed by 4 digits (d{4}).

Now that’s great but what if this isn’t just a product number but it’s actually a compound data format and that the product number is made up of a product family (OTGC) and a part number (5431) and I needed the two pieces of information separately? Well that’s where capture groups become important.

In regular expressions there is a syntax to signal that the text that you find actually consists of multiple, separate, discrete, pieces of information. As in the example with a product number such as OTGC-5431. This product number consists of two parts – 1) the product family (OTGC) and 2) the part number (5431). If you need access to the product family and part number separately you can use capture groups to split up the product number in the regular expression itself instead of relying on parsing after recognition.

So instead of simply getting a match of “OTGC-5431” you also get information that the product family is “OTGC” and the part number is “5431”.

So how does one use capture groups?

Well you start with the regular expression above and then you add capture groups by simply changing it to be

([A-Z]{4})-(d{4})

Notice how I only added two sets of parentheses. That all. That tells the regular expression engine that the result is made of of two parts. So instead of getting just one result (OTGC-5431) I get three: OTGC-5431, OTGC, 5431 (the match in it’s entirety and the two capture groups).

So how do I use these results in MyWidgets / LiveText? Well let me walk you through an example.

Lets imagine that you have a web service that allows you to search for product numbers but need the product family and part number separately. The syntax is something like http://www.example.com/prodquery?pf=<product family>&pn=<part number> (http://www.example.com/prodquery?pf=OTGC&pn=5431). Let me show you, end to end, how to do this using MyWidgets and LiveText.

  1. Start by creating a new widget. Choose to create a web widget and click Next.
  2. Now specify the URL as being “http://www.example.com/prodquery?pf=OTGC&pn=5431&#8221; (Please note: The address doesn’t point to anything but it proves the point we need). Now click Next.
  3. A GET request is fine – just click Next.
  4. Now the web page is fetched. As we know the URL we specified doesn’t work just click Next.
  5. In the “Configure a Widget” dialog name the widget “Demo Product Search” and choose “Wire as an action” at the bottom. Then click the “Advanced” tab at the top.
  6. Put a checkmark in both boxes in the “Configure” column as we need to map both URL parameters to our recognized LiveText. Then click Next.
  7. We need a new recognizer to recognize our product number. To do this click the “New Recognizer…” button.
  8. Name the recognizer “Demo Product Number” in the top text box. Now since our recognizer uses two capture groups we need to tell Notes how to map these to our widget (as widget properties) so we need a new Content Type. To do this click the “New Type…” button.
  9. In the “Configure a Content Type” dialog box you name the parts of the text you recognize. We have two parts so we click the “Add”-button twice and fill the text fields like specified below. We do this to indicate we have two properties called “pf” and “pn”. Then click OK.
  10. Back in the “Configure a Recognizer” dialog our new Content Type (“Demo Product Number”) has been chosen for us. Now we specify our regular expression with the two capture groups. Then we click the “Add”-button twice and map capture group 1 (the “product family”) to content property “pf” and capture group 2 (the “part number”) to content property “pn” as shown below. Then click OK.
  11. Back in the “Wire an action to configure a widget” dialog our newly created recognizer has been chosen for us. Now we need to map the widget properties (the parts of the recognizer) to the URL parameters. We do this on the “Advanced” tab so click on that near the top.
  12. On the “Advanced” tab add a second parameter box by clicking the “Add”-button and map the URL parameters to our widget properties as shown below. Then click Finish.

Now take a deeeeeeeeeeeeeeeeep breath… 🙂

That’s what’s required to create a new widget with a new recognizer and new content type. It may seem like much, and I think it is, but remember that you may now add a second web widget that uses the same recognizer by following the same steps but ignoring step 7-10. Also when you’ve done it a few times it becomes second nature and you use it all the time. I do.

Now we need some text to test on. Create a new e-mail message, add a subject, some text to the body field including a couple of product numbers and e-mail the message to yourself. To make it easier you may copy/paste the below text:

Ullamcorper veniam aliquip duis, vel vero dolore in dolor
aliquam dolore lobortis delenit vel duis, magna. Eros
iusto, consequat iriure eu enim nulla exerci minim nulla
facilisis, ex te ut nulla volutpat qui: OTGC-5431,
OTMM-6615. Odio nulla amet ea quis volutpat suscipit exerci
eros et dolore feugiat, ea dolor ad, vulputate, delenit
enim sed autem tation enim zzril blandit iusto. Dolor
facilisi vero feugait iriure, et consequat ut, et euismod
ipsum praesent quis duis zzril in hendrerit, at et, dolor
hendrerit dignissim. Ut commodo odio consequat, onsectetuer
augue dignissim nulla dolore velit.

Now when you open the message from your inbox you should see something like this:

As you can see the Notes client recognized two text strings as shown by the blue dotted lines. If you hover over the text and click the down arrow (will appear to the right of the text) you’ll see a small menu as shown below. From that menu select “Display Demo Product Number Properties”. That will show a dialog box explaining exactly what Notes found and what text goes into which capture groups and hence into which widget properties.

In the next post in the series I’ll show how to use these widget properties from a Java action. Stay tuned…

MyWidgets just got better – Option to specify a custom widget icon for sidebar

Please note: The following is from the release notes of Notes 8.5.2 so I don’t take credit for writing this. Lotus Notes 8.5.2 is in beta and there are no guarantees that the features described here will be in the final product that IBM ships.

Power users and administrators can add a new viewImageUrl attribute to the palleteItem element in a widget’s extension.xml definition to specify a custom icon to use in the sidebar view/title bar for that widget. The viewImageURL attribute value must be a URL to the desired image, for example:

viewImageUrl="http://my.server.com/myImage.ico"

Example widget XML syntax is shown below:

MyWidgets just got better – Option to set default widget double-click action

Please note: The following is from the release notes of Notes 8.5.2 so I don’t take credit for writing this. Lotus Notes 8.5.2 is in beta and there are no guarantees that the features described here will be in the final product that IBM ships.

You can now set a default double-click action to open widgets in the sidebar, a new window, a float window, or a tab. The default does not impact widgets that have a pre-defined double-click action defined in their XML. The supplied default is newWindow.

Note: See Tech Note 1399534 “Adding a widget custom double-click action” for information about customizing an individual widget’s double-click action. (Red: I was unable to find this technote – maybe it hasn’t been published yet).

This change enables the control of what action is taken when you double click on a widget in the My Widgets sidebar panel. The default will act on all widgets that do not already have a pre-defined double click action. The new plugin_customization.ini file preference is

com.ibm.rcp.toolbox/doubleClickAction=<option>

where valid values for <option> are:

  • sideBar
  • newWindow
  • float
  • tab

For example, to set the default double-click action to open the widget action in the sidebar, add the following statement to the user’s local plugin_customization.ini file:

com.ibm.rcp.toolbox/doubleClickAction=sideBar