Posts Tagged With: OpenNTF

Showing a database in a panel in #IBMNotes

I’d never understood the whole ‘widgets’ thing that got added to Notes, where you could have additional things in that right-side set of panels. At first, I put Linked In over there, thinking I’d use it to look up people and keep track of discussions. I never did use it and eventually, it would just show me a login box, so when I changed laptops, I didn’t bother putting it back. I tried some RSS feeds, but they were far too chatty for me to ever keep track. However, I found a great use for them this past month: quick access to back-end of XPages databases.

In our environment, we put all the XPages and custom controls into one ‘design’ database and almost all of the data into another. You guessed it, the almost all is the problem. Some of the configuration documents have to reside in the design database, so it knows where the data resides. I want the users to double-click on the icon and simply open the application in XPiNC, rather than accidentally seeing the man behind the curtain. So, I put a link in the home page of our application that opens the views in Notes:

<xp:link escape="true" id="link1" text="Open Notes views" style="position: absolute;z-index:100;top:25px;left:750px;">
	<xp:this.rendered><![CDATA[#{javascript:var roles = context.getUser().getRoles();
	return @IsMember("[WFAdmin]", roles);}]]></xp:this.rendered>
	<xp:this.value><![CDATA[#{javascript:var server:NotesName = session.createName(@Subset ( @DbName(), 1));
		var filepath = database.getFilePath();
		return "Notes://" + server.getCommon() + "/" + filepath + "/TSWFKeywords?OpenView";}]]>
	</xp:this.value>
</xp:link>

That works fine, but you have to navigate back to the home page to get the the link. I could put it everywhere, but as I was looking at the Drag n Drop sidebar per a request from our newly acquired office in the UK, I figured out that creating the XML files and putting them among your widgets was really easy.

Just create a file with an XML extension — it can have any name, so I tend to create them with meaningful names, like “APPS1 Shared Resources Engage.xml” — with a format similar to this:

<?xml version="1.0" encoding="UTF-8"?>
<webcontextConfiguration version="1.1">
<palleteItem contributeTabOnStartup="false" 
contributeToSideshelfOnStartup="true" 
hideThumbnail="false" 
id="APPS1SharedEngage" 
imageUrl="" 
providerId="com.ibm.notes.toolbox.provider.NotesViewPalleteProvider" 
singletonSidebar="false" 
title="ENGAGE SR" 
url="Notes://APPS1/Projects/Philippines/Engage/EngageSharedRes.nsf" 
viewImageUrl="">
<preferences/>
<data TYPE="DEFAULT"/>
</palleteItem>
</webcontextConfiguration>

I know five of the values that you can edit….

Line Meaning
contributeTabOnStartup=”false” If you want it to always open as a regular tab when you open Notes, set this to true. Otherwise, set this to false.
contributeToSideshelfOnStartup=”true” If you want it to always open as a panel on the right, set this to true. If you’d prefer to double-click and have it open in a new window, set this to false.
id=”APPS1SharedEngage” The unique ID for this widget. If you drag-and-drop another XML file with the same ID, it will update the existing one. When you create one using the menus, it supplies a random numeric one, but text also works, so I’d recommend that using meaningful, text ones.
title=”ENGAGE SR” This is what displays on the icon in the sidebar and on the panel header if you load it in a panel.
url=”Notes://APPS1/Projects/Philippines/Engage/EngageSharedRes.nsf” The Notes URL that you want to open. You can specify a view, but when I tried to specify an agent it didn’t execute the agent. I also tried to specify the XPage, but it never loaded. So, either the database or a specific view (with /viewname?OpenView after the filepath)

Then, drag and drop that XML file from your file system onto the My Widgets panel. In the one I have above, it always opens in a panel on startup, so I can access the views quickly and easily. However, we’re going to have 70 of these at any one time once we roll out our design to all of our projects, so I’ll probably not have any load on startup. If you don’t load them, on startup, double-clicking opens them as a new Notes window.

As soon as I finish figuring out how we’re going to configure the Drag n Drop widget, I’ll post on how to do that. While there is documentation on OpenNTF, I think I can provide some more insight and may look at doing some enhancements down the road.

Advertisements
Categories: Old Notes | Tags: , , | Leave a comment

Dirty pages and keeping users on them in #XPages

As I’ve mentioned before, sometimes XPages does not react the way your Notes users would expect it to react. In particular, I’ve had issues with ensuring that XPages warns the user when they try navigating away from a page that they’ve edited without first saving it. Such pages are “dirty”, since something has changed on them. Back in November we examined this in my post on Modified flags in XPages.

Unfortunately, sometimes I want to inform the user that they’re leaving a dirty page and other times I don’t. Also, sometimes, I seem to be able to add things that don’t warn the user that they’re leaving a dirty page. I’m sure there is consistency, but I haven’t figured out the rules, so I have added some code that handles these situations.

Simple warning of a dirty page

This was described in that prior post. Set the enableModifiedFlag to true and provide a couple of properties to handle it. This should fire whenever you close the XPage or navigate away via a standard link.

<xp:view xmlns:xp="http://www.ibm.com/xsp/core" enableModifiedFlag="true">
	<xp:this.modifiedControl>
		<![CDATA[#{javascript:if ( true ) {return "saveButton1"}}]]>
	</xp:this.modifiedControl>
	<xp:this.modifiedMessage>
		<![CDATA[#{javascript:"Purchase order modified. Click OK to save, cancel to continue without saving"}]]>
	</xp:this.modifiedMessage>
...
</xp:view>

Unfortunately, I’ve found that sometimes, it doesn’t warn me.

Warning when clicking links

I’ve got some navigation on the left side of my XPages, set up in a lovely dojo accordian with links to different parts of the application. However, not every link is set up in the same way. Some are simple and use the modifiedControl to warn users, like this one:

<xp:link text="Attachments" escape="true" id="link3" value="/att_attachmentManagement_view.xsp">
</xp:link>

Some, however, run some scripts to remove some sessionscope variables when switching pages and I was having challenges getting the server-side Javascript to execute. So, I found a way to do both:

<xp:link text="Payment requests" escape="true" id="paymentLink" target="_self" value="#">
	<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
		<xp:this.action><![CDATA[#{javascript:clearDynamicViewSettings();
context.redirectToPage("/pro_paymentRequest_view.xsp");}]]></xp:this.action>
	</xp:eventHandler>
</xp:link>

The unfortunate thing is that when I’m using the redirect, it ignores the dirtiness of the page. Fortunately, Per Henrik Lausten found a way to deal with it on StackOverflow (thanks to PSolano), and posted it as an XSnippet on OpenNTF.

if (XSP._isDirty()){
  if (confirm ("Are you sure you want to navigate away from this page?" + "\n" + "\n" +
    "This document may contain unsaved changes." + "\n" + "\n" +
    "Press OK to continue, or Cancel to stay on the current page.")) {
    return true;
  } else {
    return false;
  }
} else {
  return true;
}

So, when I added that explicitly as client-side Javascript to each eventhandler, it worked beautifully. Now, being a fan of reusable code, I wanted to put it in a CSJS script library and invoke the function all over the place. My function was as shown above, with a little wrapper:

function isClean() {
	if (XSP._isDirty()){
	    ....
	}
}

Then, I just needed to invoke it. My first attempt looked great to me. Call isClean() and the client side would warn the user, then stop them as appropriate.

<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
	<xp:this.action><![CDATA[#{javascript:clearDynamicViewSettings();
context.redirectToPage("/pro_paymentRequest_view.xsp");}]]></xp:this.action>
	<xp:this.script><![CDATA[isClean();]]></xp:this.script>
</xp:eventHandler>

Ummmm, but that didn’t work. In order to prevent the server-side Javascript from executing, the client-side Javascript needs to RETURN false, not just compute it.

<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
 <xp:this.action><![CDATA[#{javascript:clearDynamicViewSettings();
 context.redirectToPage("/pro_paymentRequest_view.xsp");}]]></xp:this.action>
 <xp:this.script><![CDATA[return isClean();]]></xp:this.script>
</xp:eventHandler>

That’s added bonus knowledge – not only are we learning how to stick to dirty pages, we’ve also learned that if you have the CSJS return a value of false, it will not execute the SSJS. I’m sure you can grasp the opportunities for validation provided there.

What about when you don’t want to warn them?

In our application, the user can select the action to perform from a combobox and then click a button to execute it. (Thanks to Scott Good, Henry Newberry and the folks at Teamwork Solutions!) The challenge here is that when the user changes the value in the combobox, the page is dirty! I mean, no data may have changed other than that combobox, but the XPage still feels dirty. Since some of those actions will result in saving the document and all of them result in navigation away from this page in an expected and managed way, we don’t want it to feel dirty. To dodge the problem, I just add a little CSJS to convince that page that it’s not really dirty.

<xp:this.script><![CDATA[XSP._setDirty(false,"");]]></xp:this.script>

So, then the modifiedControl is not tipped off and we execute the intended commands. Now, I’m pretty sure we don’t run into this problem with standard save buttons, but we’re in an unusual case of taking two steps to execute one action.

Note

YMMV. These private calls to XSP methods may go away and using them requires care to ensure you’ve got the right parameters, or so the XPages Portable Command Guide advises us. Of course, everything we code may call functions that will go away and we always need to get the parameters right. So, I’m gonna use them, though sparingly.

Categories: Client-Side Javascript, Server-Side Javascript, Xpages | Tags: , , , , , , , , , , , , | Leave a comment

Create a free website or blog at WordPress.com.

%d bloggers like this: