Wednesday, March 20, 2013

Fix for partial refresh on Dojo Tab Container/Content Pane

I wrote this a while back, but I couldn't find that I'd shared it.

You need to use the partial refresh hijacker to use the code snippet.

This code snippet initializes Dojo Tab Containers/Dojo Content Panes in the area that's refreshed:
// Fix problem with partial refresh on Dojo Tab Container/Content pane
// Source for inspiration:
// http://www.openntf.org/projects/pmt.nsf/0/D228115FAA98DDEC86257A7D0050E7FF
dojo.subscribe( 'partialrefresh-complete', this, function( method, form, refreshId ) {
 var tabContainersAndContentPanes = dojo.query( '[id=' + refreshId + '] .dijitTabContainer[widgetid], ' +
  '[id=' + refreshId + '] .dijitContentPane[widgetid]' );
 if( tabContainersAndContentPanes.length === 0 ) {
  return;
 }
 
 for( var i = 0; i < tabContainersAndContentPanes.length; i++ ) {
  var widgetId = tabContainersAndContentPanes[i].getAttribute( 'widgetid' );
  var widget = dijit.byId( widgetId );
  if( widget ) {
   widget.startup();
   widget.resize();
  }
 }
} );

Add the code snippet in a dojo.addOnLoad function or something similar.

If you have other widget types that fails to initialize, just modify the selector/startup commands to fix.

Friday, January 18, 2013

Small LS class that can be used to check if fields have changed

We've had some issues with semaphore locks on one of our import databases. The import database has routines that import/update data, then replicate it to a cluster when it's done.

We're not exactly sure what triggers the locks, but the server crashed sometimes several times a day, so we decided to see if the import routines could be optimized to do as few writes as possible.

Several of the routines saved documents even if there were no field changes. I wrote a simple class to test for field value changes.
'// Used to test if certain fields have changed
Class FieldChangeChecker
 Private fieldsToCheck As Variant
 Private fieldValues List As Variant
 
 '// Run this after calculcation/etc. to see if specified fields have changed
 Function haveFieldsChanged( doc As NotesDocument ) As Boolean
  On Error GoTo bubbleError
  
  If doc.isNewNote Then
   haveFieldsChanged = True
   Exit Function
  End If
  
  Dim initialValue As Variant, currentValue As Variant
  ForAll fieldName In Me.fieldsToCheck
   initialValue = Me.fieldValues( fieldName )
   currentValue = doc.getItemValue( fieldName )(0)
   
   If initialValue <> currentValue Then
    haveFieldsChanged = True
    Exit Function
   End If
  End ForAll
  
  Exit Function
bubbleError:
  Error Err, errorMessage()
 End Function
 
 '// Comma separate field names. E.g. "forename,surname"
 Sub New( ByVal commaSeparatedFieldNames As String )
  On Error GoTo bubbleError
  
  Me.fieldsToCheck = FullTrim( Split( commaSeparatedFieldNames, "," ) )
  
  Exit Sub
bubbleError:
  Error Err, errorMessage()
 End Sub
 
 
 '// Run this before calculation/etc.
 Sub readInitialValues( doc As NotesDocument )
  On Error GoTo bubbleError
  
  ForAll fieldName In Me.fieldsToCheck
   Me.fieldValues( fieldName ) = doc.getItemValue( fieldName )(0)
  End ForAll

  Exit Sub
bubbleError:
  Error Err, errorMessage()
 End Sub 
End Class
Example of use:
..
Dim fieldChangeChecker As New FieldChangeChecker( "FirstName,LastName,Address,PostCode,City" )
Set customerDoc = customersView.getFirstDocument()
While Not customerDoc Is Nothing
 Call fieldChangeChecker.readInitialValues( customerDoc )

 '// Code that looks up the newest information and sets fields

 If fieldChangeChecker.haveFieldsChanged( customerDoc ) Then
  Call dataDoc.Save(True, False) 
 End If

 Set customerDoc = customersView.getNextDocument( customerDoc )
Wend
..
Regarding the errorMessage-function in the class. I use error bubbling in all my LS code. If something fails somewhere in a routine, I want the routine to stop executing. At the top of the stack, I use OpenLog/LogError. This gives me a nice pseudo stack of the function calls.
Code for errorMessage function:
Function errorMessage As String
 '// Simple function to generate more readable errors when dealing with error-bubbling
 Dim message As String
 message = Error
 
 If CStr( GetThreadInfo(10) ) = "INITIALIZE" Then
  errorMessage =  "Error " & Err & " on line " & Erl & " in function " & GetThreadInfo( 10 ) & ": " + Error
 Else
  errorMessage =  Chr(13) + Chr(9) + "Error " & Err & " on line " & Erl & " in function " & GetThreadInfo( 10 ) & ": " + Error$ 
 End If 
End Function

Friday, October 12, 2012

Code Snippet - Close dialog if all fields are valid

Today I was working on a dialog that had fields with validation. I only want to close the dialog if all fields are valid. I'm not aware of any inbuilt XSP methods that does this. This code snippet checks for any invalid fields in the dialog. If all fields are valid, the dialog is closed.
function closeDialogIfValid( dialogId ){
 var invalidCount = dojo.query( '[id="' + dialogId + '"] [aria-invalid="true"]' ).length;
 if( invalidCount === 0 ){
  XSP.closeDialog( dialogId );
 }
}
This probably only works if you're using server side validation.

If there is something like this in the XSP API, please let me know.

Share and enjoy!

Thursday, September 6, 2012

Snippet to clear session for user

During testing, I sometimes log in as different user to test hide/whens/etc. I used to delete the SessionID cookie in the browser to clear session scoped beans/sessionScope variables. Today, I looked for a solution to automate this. This line will clear all objects related to a session:
facesContext.getExternalContext().getSession( false ).invalidate();
If you want to clear session when logged in user changes for the current "XPages" session, here's the snippet I use (put the code in afterPageLoad or beforePageLoad):
// Reset session when user changes
var currentUserName = sessionScope.currentUserName;
var userName = session.getEffectiveUserName();
if( currentUserName && userName !== currentUserName ){
 facesContext.getExternalContext().getSession( false ).invalidate();
}   
sessionScope.currentUserName = userName;
I would think this is better than deleting the cookie, as the server is immediately notified that it should flush the objects bound to the session. When I delete the cookie, I believe that the objects are kept in memory until a specified timeout.

Monday, August 20, 2012

Comprehensive guide to Design Definitions

I found this guide in IBM's Application Development wiki while looking for information on Design Definitions:
Native and Custom Control Custom Visualization Best Practices

So far it's the most comprehensive guide to Design Definitions I've found.

Friday, July 27, 2012

XPages - Grouping data in comboboxes

I wanted to have some values grouped in a ComboBox. Not sure if it's possible to do with pure SSJS (without using the Java API), but found a way using beans:
JSF Tree in a dropdown (see accepted answer).

The resulting html is select node with options grouped in optgroup nodes.