Wednesday, December 9, 2009

Sloppy multi-value implementation in XPages

Update: Demoapp for testing the bug
Update 2: Code for Custom Converter that helps work around the problem

I reported this to IBM today (my first Service Request). I thought I should share the bugs, so others are aware of it.

Bug with multi-value fields and converters in XPages


By multi-value field, I mean a field that have the multi-value 
separator set.

When saving a multi-value field of type String, the value alternates
between being split into multi-value, and being a flat string.
First save -> multi-value
Second save -> flat string
Third save -> multi-value

When saving a multi-value field of type date or number, the field only saves
the first value.

I also tried using a custom converter to modify the field
(getAsObject -> split, getAsString -> join). This doesn't work at all.
It seems custom converters only can be result in string values.


Example:


How hard can it be to implement multi-value. It seems like someone slapped together a couple of lines of code, and forgot to test it. I'm surprised that there isn't any other bloggers haven't written about this. Maybe multi-value fields aren't that popular?

Thursday, December 3, 2009

Helper-functions for debugging XPages

Update: Modified the class to support HTML in the message
Update 2: Made the code compatible with Domino 8.5.2
Update 3: Added methods to display message/exception on page
Update 4: Modified to send to current user. If on localhost, the exception/message is thrown -> xpage shows stack trace.

Since there are no good tools for debugging XPages, I created a couple of helper-methods (Server Side Javascript) of my own.

Debug.message sends a (MIME/HTML) mail with the specified message

Debug.exception sends a stack trace of an exception (used in a try/catch). This is useful because not all exceptions crash the application (for instance AfterRenderResponse code).

// Helper-class for debugging
var Debug = {
// Send a stack trace of an exception
exception: function( exception ){
// If on localhost/public db - throw exception
if( this.getUserName() === 'Anonymous' ){ throw exception; }

this.message( this.getExceptionString( exception ), 'Exception!' );
},

// Add exception to page
exceptionToPage: function( exception ){
this.setPageDebugMessage( 'Exception: ' + this.getExceptionString( exception ) );
},

getExceptionString: function( exception ){
var errorMessage = exception.message;

if( typeof exception.printStackTrace !== 'undefined' ){
var stringWriter = new java.io.StringWriter();
exception.printStackTrace( new java.io.PrintWriter( stringWriter ) );
errorMessage = stringWriter.toString();
}

if( typeof exception === 'com.ibm.jscript.InterpretException' ){
errorMessage = exception.getNode().getTraceString() + '\n\n' + errorMessage;
}

return errorMessage;
},

getUserName: function(){
return @Name( '[CN]', @UserName() );
},

// Send a message (supports HTML)
message: function( message, subject ){
// If on localhost/public db - throw exception
if( this.getUserName() === 'Anonymous' ){ throw 'Not logged in. Could not send message: ' + message; }

session.setConvertMime( false );
var doc:NotesDocument = database.createDocument();
doc.replaceItemValue( 'Form', 'Memo' );
doc.replaceItemValue( 'Subject', subject || 'Debug..' );
doc.replaceItemValue( 'SendTo', this.getUserName() );

var body:NotesMIMEEntity = doc.createMIMEEntity();

var contentStream = session.createStream();
// Set preferred styling
contentStream.writeText( '' );

// Convert linefeeds to <br>s
contentStream.writeText( message.replace( '\n', '<br />' ) );
body.setContentFromText( contentStream, 'text/html;charset=ISO-8859-1',
lotus.domino.MIMEEntity.ENC_NONE );
doc.send();

session.setConvertMime( true );
},

// Add message to page
messageToPage: function( message ){
this.setPageDebugMessage( message );
},

// Adds message to the bottom of the page in a dynamically created xp:text
setPageDebugMessage: function( message ){
var messageControl = getComponent( 'global-debug-messages' );
if( !messageControl ){
messageControl = new com.ibm.xsp.component.xp.XspOutputText();
messageControl.setId( 'global-debug-messages' );
messageControl.setEscape( false );
messageControl.setStyleClass( 'xspMessage' );

var valueBinding = facesContext.getApplication().createValueBinding( '#{requestScope.debugMessages}' );
messageControl.setValueBinding( 'value', valueBinding );

view.getChildren().add( messageControl );
}

var currentMessages = requestScope.debugMessages;
if( typeof currentMessages !== 'string' ){ currentMessages = ''; }
requestScope.put( 'debugMessages', message + '<br />' + currentMessages );
}
}

Tuesday, December 1, 2009

Server side event handling - get value without having to use getComponent

If you type this.getParent().getValue(), you will get the value of the component that holds the event handler.

this.getParent() returns the component that holds the event handler.

this is the EventHandler object.

Thursday, November 26, 2009

XPages Type Ahead - use var property to get field value

I've seen several examples on type-ahead using getComponent( 'componentId' ).getValue(). Using hard-coded field id's can be a bad idea in the long run. If someone changes the id of the type-ahead field, the type-ahead will fail. There's a more maintainable alternative, the var property of the typeAhead-component.

It's not directly available on the field. If you select the <typeAhead>-node in the source, you will get an "All properties" view for the Type Ahead component. Under data, you can set the var property.



If you, like me, like modifying source-code better, add a var attribute to the typeAhead node.



In the suggestions-code, you can now do:
@DbLookup( [ @DbName()[0], 'database.nsf' ], '(lupView)', lupKey, 1, '[PARTIALMATCH]' )


Another tip: Although you can compute Type Ahead on and off in the field, after the field loses focus, it looks like Type Ahead is always enabled. If you select the <typeAhead>-node, you can modify the rendered property (enables/disables type-ahead).

Tuesday, November 17, 2009

Useful formula cheat sheet

Just found this while browsing. Domino Formula @Functions. It's more or less a cheat sheet with @-functions sorted in a logical order.

It's actually made by Lotus, for Notes 6.5. You probably need an A3 printer to transfer it to paper.

Share and enjoy!

Tuesday, November 10, 2009

XPages: Creating a Data Table programmatically on page load

I've finally started working on a proper XPages application at work, so now my inspiration is bubbling.

Todays demo is (hopefully) a precursor to something that will be very useful to you, my readers. I started looking for a way to dynamically creating a Data Table control. Since XPages still is in its infancy, documentation and examples-wise, I had to go look for information on JSF (which XPages is built upon).

I found this great resource. The classes used for UIComponents in XPages have different names than the standard JSF-classes, but the syntax is more or less the same.

To find the XPages equivalent classes, I create the component I want to find the class for. Set an id to it. Then I create a computed field with the value of typeof getComponent( 'componentId' ). This returns the full class name of the component. E.g. the class for DataTable is com.ibm.xsp.component.xp.XspDataTableEx.

In the demo I've made, I create a Data Table control inside an empty Panel component. The panel's data binding is a sessionScope variable. The XPage has a couple of buttons that lets you change the data of the table. The buttons do a partial update on the dynamically created table.

Screenshots of demoapp:






>> Download demoapp

This "technique" can easily be used for programmatically modifying existing Data Tables at runtime as well. Take a look at the code, and get inspired.. :)

Share and enjoy!

Monday, November 9, 2009

CKEditor integration with XPages (32k limited)

I've found a way around the 32k-limit. Read more here.

I've been asked several times to make an XPages integration with XPages. I finally buckled under the pressure last friday.

Initially I planned on making a full integration (no limits, bound to a NotesRichtextItem). Unfortunately, this is impossible using regular XPages components. I've tried a lot of hacks (rendererType, converting the field in different events, and a lot of other stuff I know nothing about), but so far I've been unable to make the integration work with the native XPages Rich Text editor control.

The last person that requested the integration was "fine" with a 32k limit on the demo, so I've extended the CKEditor Integration demo with a demo of XPages integration (bound to a regular text field).


Read the blog entry on CKEditor integration for prerequisites (CKEditor installed in a certain directory on the server).

>> Demoapp of CKEditor integration with Domino form and XPages

Wednesday, October 7, 2009

Technique: Using a Page as a cross language template/string container

In this demoapp, I use a page as a definition for an XML-representation of a document. It is related to a project at work, where we send XML to a web service. This service is to be called both from the Notes Client, and from an XPage. I could script the XML in both the agent and the XPage, but this could easily develop into a maintenance nightmare.

In the demo, I've used the body of a page as a token string (separated by ¤). The first token is the field-definition. This is to be used in a formula evaluate towards a NotesDocument. The second part is the template itself.
"first_name":"last_name":"company":"address":"age"
¤
<character>
<first_name>[first_name]</first_name>
<last_name>[last_name]</last_name>
<company>[company]</company>
<address>[address]</address>
<age>[age]</age>
</character>

By having the field-definition in the page, you just have to update the page if you want more field values.

I wrote three different script libraries, each having more or less the same functionality. One LotusScript library, one Java (Script) library, and one ServerSide JS library. The libraries contain functionality that extracts the body of the a page based on its name (using a NotesNoteCollection of the pages in the DB).

I also wrote a LS agent, a Java Agent, and a XPage (acting as an agent). Each of them prints XML (based on the template) for the first document in a certain view.



This technique can also be used if you have a big string that is used in code written in multiple languages. If it's Java-code you're writing, and need a big string, this may be an easier way to maintain the string. Another thing that occurs to me is if you generate the same XML/HTML/etc. in multiple databases, you can maintain the String-template in one database, and use Design inheritance to spread it (or get the page from another database using otherDatabase.CreateNoteCollection(false)... )).

As with all techniques, this might not be the right tool for your job. Weigh pros and cons before you decide to use it/not use it.

>> Download DemoApp (open the app in a browser to test the demos)

Comments/critique/bugreports are as always welcome. :)

Thursday, October 1, 2009

Not satisfied with Domino Designer documentation? Make your voice heard!

Got this in the mail yesterday:
Key team members are available exclusively on the LotusUserGroup.org
moderated forum through this Friday to read your feedback, respond,
and provide insight regarding functionality and content. All
questions, opinions, experiences, and feedback are welcomed.

Lotus Domino Designer documentation moderator team includes:
- Bob Harwood, the Information Development (ID) Lead for Domino
Designer
- Cara Viktorov, ID Customer Feedback Lead
- Steve Shewchuk - Designer ID manager
- Deanna Drschiwiski - Designer Information Architect
- Michael Stewart - Writer
- Bob Perron - Writer

See what your peers have already posted and participate at
http://www.lotususergroup.org/lotusforum


Domino Designer Forum

Thursday, September 24, 2009

Avoid using reserved words in JavaScript

A former colleague of mine had an obscure problem with one of his applications. As far as I understood him, there weren't thrown any errors, but the application behaved weirdly in some situations.

Turned out that the cause of the problem was that he used a had a variable called name. name is a reserved word in the JS implementation of the browser (at least in IE).

While I can't remember the last time I stumbled onto this problem, I'd thought I'd share a list of reserved words in JavaScript/the browser implementations of JavaScript, in case any of my readers struggle with this.

To be on the safe side, never call a variable the same as a reserved word.

Monday, September 21, 2009

Interesting talk about Server Side JS

From YUI theater.



Some valid points about advantages with programming in JS in the client and on the server.

Tuesday, September 15, 2009

Finally! CKEditor integration with Lotus Domino

It's been over a year since I posted my demoapp of FCKEditor-integration with Lotus Domino.

The CKEditor (the new and improved!!! version of FCKEditor) has been out for a little while now. At first, the upload integration wasn't documented, so I didn't want to waste time reverse engineering the functionality.

I got a mail a couple of days ago from a reader about CKEditor-integration with Domino. I replied that I would create a demoapp of the integration as soon as the upload functionality was documented. Now it is (more or less).

The new API for FCKEditor is BIG, but that doesn't show on the CKEditor. Its fast as *insert something extremely fast*. Test out their demo if you don't believe me!

The only thing that's changed since the FCKEditor demoapp is the $$Return on the (f)ckupload form, and the hooks I use to rewrite the name of the upload field.

I tested the demoapp in IE8, Firefox 3.5, and Opera 10. Let me know if it doesn't work for you.

CKEditor must be installed in the ..data\domino\html\js folder (you have to create the js folder if you don't have one already). Test http://yourdomain.com/js/ckeditor/ckeditor.js to see if CKEditor is in the correct folder.

This also works on localhost, if you want to experiment on your own computer.

Read the FCKEditor-integration with Lotus Domino post as well. I may have forgot to mention some details.

Anyways, it's time to go to bed. Another day, another dime tomorrow.

>> Demoapp of integration with CKEditor

Monday, September 14, 2009

XPages Custom Control - getComponent/hash of all clientIds from the browser

Until IBM implements getComponent in the browser, I've made a litte experimental custom component that lets you do something similar to getComponent in server side scripting. So far it only works with unique components (doesn't work with repeated items).

The component adds a script-tag at the bottom of the page, using the output stream that you get from facesContext.

The API is small:
Application.renderedIds
An object containing { designerId: clientId(s) } for all (?) components in the XPage. If there are multiple versions with the same designer id, you'll get the wrong id. (see comments)

Application.getComponent( designerId )
Similar to the getComponent in Server side JS. Fetches the rendered id from Application.renderedIds, then uses the corresponding clientId in a document.getElementById-statement. This method will fail if you try to multiple controls that has the same designerId (repeated items for instance).



Comments/bugreports/wishes are appreciated (but I can't promise anything).

I'm probably going to start working on a big XPage application along with some colleagues in the near future, so it's not impossible that I might turn this into a client side utility component. Time will tell.

>> Demoapp with Custom Control (GetComponentClient)

Sunday, September 13, 2009

Dynamically binding server side events in XPages - Is it possible?

Update, 01.05.10: Yes it's possible!

I'm currently going through a TLCC course on XPages. While doing so, I become more and more impressed with the platform (and how detailed the course is).

Having "everything" computable leads me to believe that XPages is the one and only platform to build future web applications on the Lotus platform. The Lotus Domino<8.5 platform is great, but it's starting to show its age. For new developers starting on the "old" platform, there are a lot of strange limitations to get used to. Some limitations (32k/64k being one of the most irritating for myself) will still be present due to the NSF being the storage, but a lot of doors have been opened up.

Getting on to the topic at hand. With LotusScript, you have some NotesUI events you can bind dynamically. By dynamic binding, I mean binding events outside the design element that the events occur.

I work very little with Notes Client applications, so I don't know if the LS binding is very useful. With web applications on the other hand, it's great. All application code can be stored/maintained in one (or more) JS library.

If something isn't working on a web application that uses dynamic event binding, you only have to look one place to find and correct the error. You avoid having to dig through fields, HTMLHead statements, subforms, etc.

My question: Is there an API in XPages you can use to bind events on components/the XPage itself dynamically (outside the XPage design element), using a server side JS library?

E.g.
// When the XPage is ready to be sent to the browser, bind relevant events
view.addEvent( 'afterRenderResponse', bindCustomerEvents );

function bindCustomerEvents(){
// When the value in the zip-code field changes, get the corresponding
// city-value from server, and do a partial refresh.
var zipField = getComponent( 'zip' );
zipField.addEvent( 'change', function(){
getComponent( 'city' ).fireEvent( 'partial-refresh' );
});
}

Friday, September 11, 2009

XPages - Idea about making it easier to get components on the client side

I've ranted heavily about how I dislike the implementation of the id-attribute in XPages. I just got an idea how to make it a lot easier for developers to work with, and it shouldn't cost IBM too much to implement.

Here's my idea. I hope you like it. If IBM'ers read my blog, please leave a comment in my blog or at IdeaJam if this is doable.

Friday, September 4, 2009

Using @IsDocBeingEdited in Form formula

I didn't know (or I forgot) this was possible, but a view is aware of if a document on the web is being opened for reading/editing, so you can use one form for editing a document, and another one for opening the document.

Example:
@If( Form="Category" & !@IsDocBeingEdited ; "Overview" ; Form )


This is useful for me due to a bad application design choice in one of the application templates I manage.

Enhanced HTML generation in Domino 8.5

With Domino 8.5 web applications, there is a setting that lets you enable "Enhanced HTML generation". This generates markup closer to the HTML specifications.

Another nice thing about it is that some of the design elements (views, actionbar, outline, etc.) gets a class-attribute on its generated HTML.

For instance, the action bar table gets a domino-actionbar class. No more hacks needed to style the action bar..

I haven't found a complete documentation of all the generated classes. This is about the only documentation I found on the subject. I wish IBM would get a bigger team working on documentation. One of the reasons features aren't used is lack of documentation.

Friday, August 14, 2009

Switching the RSS feed to feedburner

The new feed. Sorry for the inconvenience..

Friday, August 7, 2009

Test if -specific- content has changed since last FTIndex

In the previous version of this test, I tested against all documents in the database.

The app I made the function for has now started using caching through documents, so the requirements for the test has changed. I now need to know if a subset of the documents have changed. The FTIndex doesn't need to be updated if the cache changes..

The updated version takes a second parameter, a Search-query. This lets you filter out only the content you're interested in.

Function contentChangedSinceLastFTIndex( db As NotesDatabase, Byval query As String ) As Boolean 
Dim session As New NotesSession

Dim lastFTIndexed As Variant
lastFTIndexed = db.LastFTIndexed

'// First test (least resource-hungry)
If Not ( db.LastModified > lastFTIndexed ) Then
contentChangedSinceLastFTIndex = False
Exit Function
End If

'// Conclusive test - test if actual documents (not design elements) have
'// been changed since last FTIndex
Dim dateFTIndexed As New NotesDateTime ( lastFTIndexed )
Dim col As NotesDocumentCollection
If query = "" Then
'// Has any document changed?
Set col = db.GetModifiedDocuments( dateFTIndexed )
Else '// Has documents fitting [query] changed since last FTIndex?

'// Adjust the FTIndexed-date by a second, to avoid getting the
'// last saved document (if the FT-index is up to date)
Call dateFTIndexed.AdjustSecond( 1 )
Set col = db.Search( query, dateFTIndexed, 0 )
End If
If col.Count > 0 Then contentChangedSinceLastFTIndex = True

End Function


Don't worry about speed. In my test-app, the search takes less than a millisecond with a close cutoff date.

Update: Leus' Mobiele wrote a Java version of the above code:
private boolean contentChangedSinceLastFTIndex( Database db, String query) throws NotesException {
DateTime dateFTIndexed = db.getLastFTIndexed();

// First test (least resource-hungry)
if ( db.getLastModified().timeDifference( dateFTIndexed ) <= 0) {
return false;
}

// Conclusive test - test if actual documents (not design elements) have
// been changed since last FTIndex

DocumentCollection col;

if (query.length() == 0) { // Has any document changed?
col = db.getModifiedDocuments( dateFTIndexed );
} else {
// Has documents fitting [query] changed since last FTIndex?
// Adjust the FTIndexed-date by a second, to avoid getting the
// last saved document (if the FT-index is up to date)

dateFTIndexed.adjustSecond(1);
col = db.search( query, dateFTIndexed, 0);
}

if (col.getCount() > 0) {
return true;
} else {
return false;
}
}

Tuesday, July 21, 2009

MooTools plugin - Remove all underlying text nodes of an element

Element.implement({
// Removes all underlying text nodes
removeTextNodes: function( startNode ){
var initialNode = this || startNode;
var childList = initialNode.childNodes;
if( childList.length === 0 ){ return; }

// Walk through all childNodes. If text - remove, else search/destroy
// potentially underlying text nodes
var currentNode;
var nodesToRemove = [];
for( var i = 0, len = childList.length; i < len; i++ ){
currentNode = childList[i];
if( currentNode.nodeName === '#text' ){ nodesToRemove.push( currentNode ); }
else { Element.removeTextNodes( currentNode ); }
}

// When all text nodes on the current level are found, remove them from the DOM
for( i = 0, len = nodesToRemove.length; i < len ; i++ ){
currentNode = nodesToRemove[i];
currentNode.parentNode.removeChild( currentNode );
}

return this;
}
});


I use this to clear/update a label that only contains a field and text. E.g.
<label id="label-with-field"><input type="radio">Some text<label>
$('label-with-field').removeTextNodes().appendText('newLabel')

The last line in the method, "return this;" makes the method chainable.

Friday, July 3, 2009

Accessible Web Forms With Domino - Addendum

I'm finally trying out what Jake probably have done for close to four years. Getting rid of "Use JavaScript when generating pages".

My addendum, is the choice of the submit element. In his article he chose <input type="submit" />. The downside with this is that the value attribute is used as a label for the button. I'm going to use <button type="submit">, which frees me to put whatever I want as a label. It makes it a lot easier to make internationalized button, as it lets you separate data from design.

E.g. (brackets indicates field)
<button type="submit" name="action" value="save">[cfd_save_label]</button>
<button type="submit" name="action" value="archive">[cfd_archive_label]</button>
<button type="submit" name="action" value="delete">[cfd_delete_label]</button>

He's probably using this already, but since I couldn't find a mention of it on his site, I thought I should share it with you.

If you're having trouble designing buttons across browsers, check out this guide.

Wednesday, July 1, 2009

HttpRequest class - Support for multivalue requests (e.g. checkbox)

A colleague of mine needed to process values from a form with checkboxes. In some instances, the amount of checked boxes (select all) was so great that he hit the 32k limit of Domino fields.

I suggested that he tried posting to an agent/used my HttpRequest class. This didn't work, as each checkboxvalue is sendt as a single parameter.

E.g. ...make_report?OpenAgent&user=tom&user=jane&user=jack

The previous version of the class only fetched the last parameter.
Dim request As New HttpRequest()
Print request.parameter("user")
' Prints jack


I updated the code, so that the class aggregates the values into a comma separated string dynamic array. Single value parameters are still Strings.
Dim request As New HttpRequest()
Print Join( request.parameter("user"), "," )
' Prints tom,jane,jack


>> The class in a txt-file

Share and enjoy!

Monday, June 29, 2009

New NotesUI-bug found in Notes 8.5 (includes workaround)

Update: The bug(?) isn't as serious as I first thought. The settings document wasn't closed, but it was sent to a frameset of another application. In the other application, an action calls NotesUIWorkspace.SetTargetFrame. I'm not sure if it is a bug, that a document from another application ends up in this frameset. For all I know this is just Notes' quirky way of doing things. If I call setTargetFrame("someRandomValue") before NotesUIWorkspace.EditDocument, the code works as designed.

--

I'm back working in the client again. It seems every time I'm working on client code, I discover a new NotesUI-bug. :-\

Purpose: When user tries to create a settings doc, check to see if one already exists. If yes, open the existing doc (by static unid), else set static unid, continue.

I'd have thought it would be as easy as (in PostOpen) Source.Close, NotesUIWorkspace.EditDocument. And it would, if the user was running Notes 8.0.X. In Notes 8.5, the client closes both the "Create Settings" instance, and the LS instance if the user opens the Settings-form when a settings doc already exists (see code below).

The workaround is easy: Source.Close, NotesUIWorkspace.URLOpen

Even though it's easy to make the code work in 8.5, I shudder to think about how many existing applications that's going to misbehave if the user upgrades to Notes 8.5.


Sub Postopen(Source As Notesuidocument)
On Error Goto handleError

Print Source.IsNewDoc 'True then False when settings doc exists

'// If new doc, check for existing settings doc
If Source.IsNewDoc Then
Dim settingsDoc As NotesDocument
Set settingsDoc = s.currentDatabase.GetDocumentByUNID( UNID_SETTINGS )

'// Set static unid on new settings doc
If settingsDoc Is Nothing Then
Source.Document.UniversalID = UNID_SETTINGS
Else
'// Open existing settings doc
Dim ws As New NotesUIWorkspace()
Call ws.URLOpen( settingsdoc.NotesURL ) 'Works
'Call ws.EditDocument( False, settingsDoc ) 'Does not work
Source.Close True
End If
End If

Exit Sub
handleError:
If Err = 4091 Then Resume Next 'Invalid UNID
End Sub


>> Bugreport

Friday, June 12, 2009

Serving correct MIME-types for Office 2007 attachments on the web

Several of our users had problems with opening Office 2007-attachments in Internet Explorer. The browser identified the attachments as zip files.

The workaround for this is to set up the Domino server to send the appropriate MIME-type header.

The correct headers

Then you need to configure the Domino Server. We hoped it would be as easy as adding config documents to the "File Identifications" view. Alas, this didn't work.

What did work was modifying the httpd file in the data-directory of the server/refreshing http
(tell http refresh).

#   Office 2007
AddType .docm application/vnd.ms-word.document.macroEnabled.12
AddType .docx application/vnd.openxmlformats-officedocument.wordprocessingml.document
AddType .dotm application/vnd.ms-word.template.macroEnabled.12
AddType .dotx application/vnd.openxmlformats-officedocument.wordprocessingml.template
AddType .potm application/vnd.ms-powerpoint.template.macroEnabled.12
AddType .potx application/vnd.openxmlformats-officedocument.presentationml.template
AddType .ppam application/vnd.ms-powerpoint.addin.macroEnabled.12
AddType .ppsm application/vnd.ms-powerpoint.slideshow.macroEnabled.12
AddType .ppsx application/vnd.openxmlformats-officedocument.presentationml.slideshow
AddType .pptm application/vnd.ms-powerpoint.presentation.macroEnabled.12
AddType .pptx application/vnd.openxmlformats-officedocument.presentationml.presentation
AddType .xlam application/vnd.ms-excel.addin.macroEnabled.12
AddType .xlsb application/vnd.ms-excel.sheet.binary.macroEnabled.12
AddType .xlsm application/vnd.ms-excel.sheet.macroEnabled.12
AddType .xlsx application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
AddType .xltm application/vnd.ms-excel.template.macroEnabled.12
AddType .xltx application/vnd.openxmlformats-officedocument.spreadsheetml.template


Not sure if it is a bug that the "File Identifications" solution didn't work..? The server-version is Domino 8.5.

Thursday, June 11, 2009

Great tool to test web applications in IE 5.5 -> 8

A colleague of mine discovered this great application, IETester. It seems to be able to run four versions of IE at once (IE 5.5, 6, 7 and IE 8).

There have been tools like this before, but all previous tools I've tried have not supported cookies, so no go for Domino login. This one does.

It's currently in early beta, but seems quite stable.

Friday, June 5, 2009

Mail from Outlook to Notes/Domino applications without Notes installed

I'm sorry to say that this post will be words only. No juicy code or bug ridden demo applications. Hopefully it will give you ideas on how to make use of this concept in your own applications.

Backstory: A customer of ours needed to get mails from Outlook into a Domino CRM web application. The prerequisite was that the users shouldn't need to install the Notes client.

This was presented to me by my boss over a couple of beers. I more or less immediately thought of the great functionality the Domino server has, that you can set up any NSF as the receiver of mails. If you could tag the mail with values inside Outlook, an agent could process the forwarded mails (add Readers/Authors fields based on customer id/etc.).

I started out with a POP3 Gmail account inside Outlook. I went through most of the writable properties of the mail-object, and struck gold. :)

The mail-object has a property called Category. When the mail is received inside Notes, this field is called Keywords. The field seems to be restricted to ASCII characters (or Gmail/Domino converts it to that). Therefore, the values need to be URL-encoded. From my small tests, everything seems to go through the wire. Line break, international characters, etc.

I send the values in a URL parameter pattern, so they're more readable, but formats like XML, CSV and JSON should work just as well. The only restriction I can think of is the ridiculous 32k limit on fields.

To let the user select the customer ID, I use the WebBrowser control inside a dialog in Outlook. The user interface is more or less a view with some DHTML code. When a user click a table row, I add a class on the row so that the user sees which customer is selected. I collect all the values from the selected table row, and put them inside a hidden field (comma separated). When the user clicks OK in the Outlook-dialog, I use VBA to collect the values from the hidden field. A second dialog is used for some custom fields (document type, date and description). That's about it.

Share and enjoy!

Thursday, June 4, 2009

UserCss: Cleaning up the Google Reader interface

I finally had enough with Bloglines. The RSS-robots are extremely slow, the page has a fair amount of downtime, the site has a lot of problems, etc.

I started using Google Reader today. The only thing I didn't like about it was all the clutter. Bloglines wastes little space.

I've known about the posibility for site-specific CSS in Opera for several years, but never had the need for it. This was the perfect occasion to try it out. I used Opera Dragonfly to identify the spots that needed to go/the items that needed to be moved.

This is the result:



(Screenshot from Opera 10 Beta1. Looking forward to being able to have the thumbnails on the left. Not usable as is.)

The stylesheet if you're interested.

In Opera, you're only able to set site-specific CSS per domain. Therefore the above CSS influences all google sites. Opera only stylesheet that doesn't affect (from what little I've tested) other google sites.

Tuesday, May 26, 2009

Conclusive way of testing if content has changed since last FTIndex

The standard way of testing, db.LastModified > db.LastFTIndexed, works great in a production environment. When you're doing performance tuning of an application that updates it's FT-index, it's not so great.

NotesDatabase.LastModified also includes changes to design elements. If you use the above test to fire a NotesDatabase.UpdateFTIndex, then the check, db.LastModified > db.LastFTIndexed, will return true until a document is modified in the db/the FTIndex is updated. Changes to design elements is ignored by the FT-indexing service on the server.

NotesDatabase.UpdateFTIndex is relatively expensive (I would think the more documents in the database -> The more time to check if the FTIndex should be updated). In an application of mine, I use NotesView.FTSearch to find certain content in views (to create HTML menu, etc). I use a class that updates the FT-index before it does the search. On regular pages, there is created two instances of this class. In an application with 200 documents, it takes the server ~130ms to do two calls to NotesDatabase.UpdateFTIndex, when the application is indexed. When I do performance tuning, I do changes to design elements, not content. Therefore the aforementioned test to determine if content has changed is flawed.

This is my so far best alternative to the "standard check". It takes 16ms to do twice in the aforementioned application. A savings of ~115ms.

Function contentChangedSinceLastFTIndex( db As NotesDatabase ) As Boolean
Dim session As New NotesSession

Dim lastFTIndexed As Variant
lastFTIndexed = db.LastFTIndexed

'First test (least resource-hungry)
If Not ( db.LastModified > lastFTIndexed ) Then
contentChangedSinceLastFTIndex = False
Exit Function
End If

'Conclusive test - test if actual documents (not design elements)
'have been changed since last FTIndex
Dim dateFTIndexed As New NotesDateTime ( lastFTIndexed )

Dim col As NotesDocumentCollection
Set col = db.GetModifiedDocuments( dateFTIndexed )
If col.Count > 0 Then contentChangedSinceLastFTIndex = True
End Function

Thursday, May 21, 2009

Help get the NotesUI-bugs in Notes 8.5 fixed

If you're having problems working with the NotesUI classes in Notes 8.5, or are planning to upgrade to Notes 8.5.x in the future/have applications that use the NotesUI-classes. Please contact Lotus Support and open a PMR to request inclusion of the fix in an 8.5 FP.

Thanks, Andre for making people aware of this issue.

Tuesday, May 19, 2009

Rearrange your Windows taskbar with Taskbar Shuffle

Update: 64-bit version of Taskbar Shuffle. The one on snapfiles/download.com doesn't seem to work with 64-bit Vista. I also found a similar program, Taskix. I haven't tried it, but from what I read on a forum, it works more or less like Taskbar Shuffle.

I recently dropped back from Windows 7 on one of my laptops to Windows XP, due to crackling sounds when playing music off my USB DAC.

One of the Windows 7 features I missed the most was the ability to rearrange the open applications in my taskbar. Thankfully, someone has made an application that lets you do this in earlier versions of Windows, Taskbar Shuffle (I downloaded it from SnapFiles).

At work, I start some applications in a certain order (hour sheet@Notepad++, Lotus Notes, Domino Designer). If Notes crashes and I have open a lot of applications, I often close all other apps, to get the order back. No more of that.

Speaking of useful applications. One of my all time favorite utility applications is Launchy. It lets you launch applications at the blink of an eye. Highly recommended if you prefer your keyboard to your mouse.

Clipboard Recorder is a must when working with code (you can also configure it to keep a history of bitmaps).

For screen capture, I use Gadwin PrintScreen.

At home, avast keeps me safe from viruses, and SUPERAntiSpyware (horrible title) is used to look for spyware.

Friday, May 8, 2009

LotusScript: Case insensitive replace

Recently, I've been working on "cloning" CMS-type applications. To avoid a lot of unnecessary work, I run an agent on the copied CMS that rewrites the UNID of the documents to that of the document in the original CMS, and rewrites local links to point to the cloned application.

Since the urls can be typed in multiple ways, the way to go for the link rewriting is case insensitive replace. This is provided in LotusScript (no need for Java).
Replace( htmlBody, webDbNameSource, webDbNameClone, , , 1 )

The last parameter tells replace that it should do a case insensitive replace.

All the parameters (taken from the documentation)
0 (default): case sensitive, pitch sensitive
1: case insensitive, pitch sensitive
4: case sensitive, pitch insensitive
5: case insensitive, pitch insensitive

Example of pitch difference: e, é, è

The CMS applications in question are web applications, so the body is text/HTML. If you're working on cross platform (Notes/Web) applications, I'd think there would be more work to clone an app (RT-navigation *shudders*).

Wednesday, April 22, 2009

XPages: Workarounds for lack of Regular Expression functionality

I wrote these two String methods as workarounds for the previously mentioned missing Regular Expression functionality.

// Finds all occurences of a substring in a string using a regular expression
// Similar to real JavaScript RegExp match with 'g' modifier
String.prototype.matchAll = function( regExp ){
// The input String
var string = this;

// Find all matches/add to matches-array
var matches = [];
while( string.match( regExp ) ){
matches.push( string.match( regExp )[0] );
string = string.replace( regExp, '' );
}
return matches;
}

// Replace all occurences of a substring using a function
// Similar to real JavaScript, where you can pass a function as the second argument
String.prototype.replaceAllFn = function( regExp, fn ){
// The input String
var string = this;

// Array used to find matches withing the string
var matchArray = null;
// JavaScript equivalent keeps track of the position of the substrings
var position = null;

while( matchArray = string.match( regExp ) ){
position = string.search( regExp );

// Replace substring(s) in the string using the supplied function
// Input parameters to the supplied function: all matches withing the
// string, the position of the match, the full string
string = string.replace( matchArray[0],
fn.apply( this, matchArray.concat( position, string ) ) );
}
return string;
}


Examples:

// Find all substrings withing braces
'{lastName}, {firstName}'.matchAll( /\{(\w+)\}/g );
// Result, array with two items: ["{lastName}", "{firstName}"]


// Map object properties to a string template
var object = { firstName: 'Tommy', lastName: 'Valand' };
var template = '{lastName}, {firstName}';
template.replaceAllFn( /\{(\w+)\}/, function( item, key ){
return object[key] || '';
});
// Result: "Valand, Tommy"

// Convert CSS to camelCase
"-moz-border-radius".replaceAllFn(/-\w/g, function( string ){
return string.replace('-','').toUpperCase();
});
// Result: MozBorderRadius

// Calculate celcius from fahrenheit
"212F".replaceAllFn(/(\d+(?:\.\d*)?)F\b/g, function(str, p1, offset, s){
return ((p1-32) * 5/9) + "C";
});
//Result: 100C


As others have mentioned, closures seems to work in XPages' pseudo-JavaScript.

Example:
function testWithClosures(){
var object = { firstName: 'Tommy', lastName: 'Valand' };
var template = '{lastName}, {firstName}';
return template.replaceAllFn( /\{(\w+)\}/, function( item, key ){
return object[key] || '';
});
}

testWithClosures();
// Result: "Valand, Tommy"


If closures weren't supported, replaceAll would crash, since the object is unavailable (undefined) in the global scope. object is only available in the scope that the "replace-function" was created.

Also, if you didn't already notice it, you can extend native objects as you can with the native objects in the web browsers. Thread carefully though.. :)

If you find any bugs in regards to the JavaScript methods being emulated, let me know.

There is (at least) one serious bug with my replaceAllFn method.
'test'.replaceAllFn( /t/, function(){ return 't'; } results in an eternal loop.
I'll try to find a better way.

Wednesday, April 8, 2009

Hotmail POP3-/SMTP access (free)

I'm not sure if it's opened up free POP3-/SMTP-service for all countries, but it seems to work in Norway. Webmail was down/I needed to reply to a reader in need, so I had to find another way to get/send my mail.

MSN Hotmail and Hotmail POP3/SMTP Access.

Friday, April 3, 2009

Forcing charset on content on the web

I hit a snag today. I needed to use the ?OpenField-command in an Ajax application to fetch utf-8 encoded content. The content seemed to be sent as ISO-8859-1. I believe the browser read it as UTF-8, which resulted in all the norwegian characters not showing correctly.

The Domino team already thought about this way back in N/D 5.02 (according to the help-file). Back then, they added a charset parameter that tells the server which charset it should send the content in. The charset parameter seems to work more or less in any context.

E.g.
http://domain.com/db.nsf/byid/someid/body_field?OpenField&charset=utf-8

Thursday, April 2, 2009

Opening EPS-files in GIMP

I had to convert an EPS-file to GIF today. This isn't possible out of the box with GIMP, which is my weapon of choice when working with images.

This guide made it possible.

Wednesday, April 1, 2009

Updated the TextToPNG-generator

Update 14.04.09: I added support for PNG transparency, and improved the vertical positioning of text to avoid clipping.

When I first made it, i called it a header-generator.

I actually needed something similar today at work, for a newsletter-application I'm working on. I added some functionality at work, and planned to release the updated version as is. I saw how horrendous the interface looked/wished for a little more functionality, so I added a little more functionality/freshened up the interface.

Old interface:


New interface:


>> Download DemoApp
Requirements to run the app: Domino 8.x (code written in Java 5)

Example images:




Question: Can XPages only be used for HTML?

The reason I'm asking is that the html/js/css code generated by your average XPage is too bloated for my taste.



I love the server side scripting/speed/pseudo-relational lookups part of the technology though.

My question: Is it possible to use XPages to generate other content than HTML, like (valid) XML and JSON, and how?

I've tried my friend Google, but he found nothing for me.

Friday, March 20, 2009

Palm Pre - Yes please!



I currently have a Nokia N95 which feels really old after watching the demo of the Palm. :\

Wednesday, March 18, 2009

New tool from Microsoft for testing web pages in various browsers

It's called Expression Web SuperPreview.

It looks very promising. Going to try it out tomorrow.

Update: Meh! The app was more or less useless compared to running browsers in Virtual Machines. The app lets you preview IE6 + your native IE version. If you have IE6 installed (which I have due to our customers lack of will to upgrade), you can only preview in IE6.

The preview is more or less an image. You can't click links/navigate to different parts of your website. To navigate, you have to type in the address. I guess it's a step up from browsershots.org, but that's more or less it.

Tuesday, March 17, 2009

Clearing floats in IE7 for Vista

I've used this method for clearing floats in my layouts.

It worked in all browsers I tested on. Then customers (using IE7/Vista) started reporting strange layout bugs that I (using IE7/XP) wasn't able to reproduce. It turns out IE7 for Windows Vista renders slightly different than IE7 for Windows XP.

I believe the main difference is when hasLayout is triggered on the styled elements.

To make the clearing of the floats work in IE7 for vista, i added this property:
height: auto

Example of fix:
/* Clear floats in the #content-element */
#content { overflow: auto; }
/* Fix for IE7/Vista hasLayout bug (resets the hasLayout property) */
*:first-child+html #content { height: auto; }

This resets the hasLayout property on the element.

The fix style rule is read/used by IE7/XP also, but it shouldn't have any negative side-effects.

Monday, March 9, 2009

Domino 8.5 generates labels for checkboxes and radio buttons

I haven't seen this mentioned anywhere, so I'll mention it.

Domino 8.5 seems to automatically wrap checkboxes and radio buttons with labels without having to modify any settings.

Pre 8.5 radio button:
<input name="some-radio" type="radio" value="some value">

8.5 radio button
<label><input name="some-radio" type="radio" value="some value"></label>

In IE6, this doesn't make much difference, but in IE7 and beyond, and most other browsers, this lets the user click the label (the text), and the radiobutton/checkbox is selected. More about labels and accessibility here.

Friday, March 6, 2009

Taking advantage of JSON from views in XPages

Since we're blessed with pseudo-JavaScript in XPages, it's time to make lookup-views with JSON columns.

If you have a well formed JSON-string, it's extremely simple to convert it to a JavaScript object.

Example:
var jsonString = '{"key":"value", "keyForNumber":2, "keyForArray":["first", "second"]}';
var jsonObject = eval( '(' + jsonString + ')' );

Result:
jsonObject = {
    key: "value",
    keyForNumber: 2,
    keyForArray: ["first", "second"]
}

Instead of making xx amount of views, have a couple of lookup-views. In the XPages, convert the JSON-string from a columnvalue to a JavaScript-object, then pick the values you need.

I've made a little demoapp of how you can take advantage of this with XPages:
>> Download

As I'm addicted to templating, I've made a simple templating-demo as well. Take a look at server side JS.

If you're lazy like me, also take a look at the (JSON\DiscworldCharacter)-view, in the lookup column.

XPages: Regular Expressions in Server Side JS are poorly implemented

I was trying to do some simple templating using JSON in XPages today, and thought: "Hey! Finally I can use the power of JavaScript regular expressions!".

I was really disappointed when I found out how poorly implemented regular expressions seem to be. I first wrote/tested the code in the FireBug console.

First fail of XPages - passing a function as the second parameter of String.replace:
var object = { firstName: 'Tommy', lastName: 'Valand' };
var template = '{lastName}, {firstName}';
template.replace( /\{(\w+)\}/g, function( item, key ){
return object[key] || '';
});
The result should be: "Valand, Tommy"
The result is: ","

String.replace in Server Side JS does not accept a function as the second parameter.


Then I thought I could use String.match to pick out all the template-parts of the string:
var template = '{lastName}, {firstName}';
template.match( /\{(\w+)\}/g );
The result should be: ["{lastName}", "{firstName}"]
The result is: ["{lastName}", "lastName"]

String.match in Server Side JS ignores the global modifier.

The worst part.. The above JavaScript code works with Client JavaScript in Notes, which I believe was introduced in Notes 5.0.. :\

I know the JavaScript in XPages is built on Java, but that is not an excuse. The Regular Expression engine in Java is even more powerful than the engine in JavaScript.

I've posted a bug-report in the forums (and ranted on my blog). Not sure if there is more I can do to influence IBM to fix this.. :\

If you want to do something along the lines of what I was trying to do. Here is my workaround-code:

function mapJsonToTemplate( jsonString, template ){
var jsonObject = eval( '(' + jsonString + ')' );

// In REAL JavaScript, string.replace can have a function as a second argument
// This is not possible in XPages JavaScript, so I have to get every item
// and replace them item by item, in a loop

var itemRegExp = /\{(\w+)\}/;
var result = template;

var matchArr;
while( matchArr = result.match( itemRegExp ) ){
result = result.replace( matchArr[0], jsonObject[ matchArr[1] ] );
}

return result;
}


mapJsonToTemplate( '{"firstName":"Tommy","lastName":"Valand"}', '{lastName}, {firstName}' )
-> "Valand, Tommy"

The reason for taking a string as input will be explained in my next blogpost, which should be along shortly.

Friday, February 13, 2009

Visual Basic macros do not work in Office 2008 for Mac

We got a question regarding an XML spreadsheet from a customer using Mac today. The macros didn't work in Microsoft Office 2008 for Mac, which they were upgrading to.

Asked my friend Google, and this is what he found for me: Visual Basic macros do not work in Office 2008 for Mac.

I don't know if Lotus Symphony supports Mac/VBA Macros, but if it did, it would be somewhat amusing.. :D

Trigger onChange immediately for checkboxes, radiobuttons and comboboxes in the Client

This was a new discovery for me. I mostly work on web applications, but the last week, I've been working in the Client exclusively.



When changing a setting on a combobox, I caught sight of the above setting, "Run Exiting/OnChange events after value change". This little gem changes the behavior of comboboxes, checkboxes and radiobuttons, so that the OnChange/Exiting events fires immediately after the user has changed the value, instead of having to wait until the field loses focus.

The setting is a per field setting, so you can mix and match according to your needs.

Thursday, February 5, 2009

Tip: Edit files as UTF-8 in DDE

Most of my CSS/HTML files are UTF-8, due to working with them in Aptana, which is set to UTF-8 by default. When working with the same files in the new editor in Domino Designer 8.5, the default format is Cp1252, which messes up my mystical Norwegian characters, æ, ø and å.

To change this, open Preferences for the designer. Goto General -> Workspace. Set Text file encoding to UTF-8 (or UTF-16 if need be).

Thursday, January 29, 2009

Serious bug in N/D 8.5 standard configuration - NotesUIWorkspace.CurrentDocument returns Nothing

Update: I got a question by mail if this bug is in the Gold release. It is. I'm running Revision 20081211.1925 (Release 8.5).

When debugging code that fetches the active NotesUIDocument from NotesUIWorkspace, NotesUIWorkspace.CurrentDocument randomly (?) returns Nothing. Sometimes the client also crashes when running code that does the above.

A couple of colleagues that work exclusively on the Client have gone back to Notes 8.0.2 because of the problem. Code that's affected by the above problem in the standard client seems to work when running the basic client.

I use this method to run the Basic Client.

A thread about the problem in the Notes 8.5 forum

If you have the same problem, please join in the discussion.

Thursday, January 22, 2009

Thoughts on XPages hijacking the id-attribute

I don't think I'm alone in thinking that the XPages hijacking of the id-attribute on fields/etc is a bad design choice. Matt White is amongst the people that have struggled with/found a way to work around the problem.

I don't think there has been much public debate around the problem. Hopefully enough people will read this post, to get a debate started, and maybe get IBM to change it's implementation in the nearby future.

With Dojo as the base framework, there is no reason for IBM to use the ID-attribute to reference elements. There is a speedy CSS selector engine available to them that enables them to use any attribute they want to, to get a pointer to an element. There is also a CSS selector API in the works, which when implemented (soon, in FF 3.1, others will follow) will allow even faster lookups.

In the still not finished HTML 5 specification by W3C/WHATWG, a data-attribute is proposed to use for storing custom values in. Since XPages is something that will last for a good while, and IBM want to play with the cool kids and follow web standards. Why not use data-attributes to add pointers for the XPages engine, and leave the id-attribute to us developers?

If it wasn't for Douglas Adams, I might not be here - Wrapping up LS09

So I learned a couple of new things during these last days. Apart from the class browser in the new LS designer, you will also get type-ahead from your own code, which I think is kind of neat. This is something you get in most of the IDEs based on Eclipse, but since I've worked in the clunky "old" designer for over three years, I'm surprised/excited by news like this.

I also heard a rumour from a former IBM employee that NSFDB2 is more or less dead. Having played around with it a little, I may understand the (not confirmed) decision. NSFDB2 doesn't seem to bring much functionality to the table. There is still the 64GB limit on Notes databases, the structure isn't easy to work with and with XPages, as Nathan proved, you are now able to do speedy semi-relational lookups with the new View Control.

On to Douglas Adams.

I was at a great dinner on tuesday, hosted by Symfoni Software. Met a lot of nice people. Amongst them, there was a guy from the Linde Group. He was from Gilford in the UK. As Gilford is the place Arthur Dent believed Ford Prefect to come from, this reminded me of Hitchhiker's guide to the Galaxy, which reminded me of my blog, which is more or less the reason I got to go to Lotusphere 2009, and also the reason I got invited to the Symfoni dinner (thanks, Trond Are). If it wasn't for Douglas Adams and his Hitchhiker's "trilogy", my blog would at least have a different name, or even worse, I might not have had a blog at all, resulting in not being at Lotusphere 2009..

On to wrapping up..

LS has been a nice experience. I learned what XPages is all about, got insight into what is planned for future versions of Domino Designer/XPages will bring, got to experience the warm weather in Florida, got a cold for walking around Epcot in too few layers of clothing, got to meet a lot of great people, got to taste the american cuisine (not to fond of the bagel), and a lot more.

This last day, I think I'll mostly stay at my room to keep the cold at bay. I'm leaving the sunny state tomorrow (just when it's starting to warm up), and I don't want to be a sneezing feverish monster. :)

Tuesday, January 20, 2009

LS09 Day two - Wrapping up

On the technology side, I learned a couple new things. XPages lets you show RichText in a view and it lets you communicate with several data sources on one page. In XPages.Next, you will be able to use XPages with SOAP and relational sources.

On the social side, I went out with IBM Norway to the Epcot centre. It was a really beautiful place. I literally know no other people going to Lotusphere, so I was a bit intimidated at first, just walking around getting boozed up. When it came to dinner, it was a bit easier. Just popped down on a random table, and started talking. As several speakers as Lotusphere have said, I didn't get bitten :)

I met a couple of new people, heard some impressions. Most of the people I've met so far on Lotusphere seems to be excited about the same technology as I (Admins partially included). The two most exciting technologies I've seen so far is XPages and Sametime Unified Telephony.

XPages for the obvious reasons(?). Sametime Telephony because it seems to make it A LOT simpler to make conference calls/etc. It's kind of a Skype for the enterprise. Usability wise, it seems even simpler to use than Skype.

More sessions to attend..

Monday, January 19, 2009

LS09 OGS - As reported by a bald guy in sandals

The OGS started great, with the Blue Man Group.

Then a small introduction from Bob Picciano, followed by Dan Aykroyd coming on stage as an alien. It might have been a reference to one of his films, but I didn't recognize his performance.

While a great speaker, I felt his jokes/etc. fit more with the american crowd than the rest of us.

On announcements.

IBM is joining forces with OpenNTF. They mentioned that they would provide code and templates, and I guess they also will provide server space/hosting.

Bluehouse changes name to Lotus Live (Engage). Sounds a bit to close to Windows Live in my ears..

Sametime Unified Telephony. This seems to bring IP Telephony to Sametime. They showed some great demos of conference calls/etc. You should be able to call to regular phones as well. Not sure how this is set up. Maybe through a third party.

Sametime Meeting - No more Java Applets. Lotus seems to have done a great deal of work on Lotus Sametime. Among the new features is being able to share documents in a meeting without the need for any (Java) plugin. All demos were showed in Firefox, so no ActiveX trickery. Videos are stored in quicktime format. Not sure why, but could be to make it more Mac friendly.

After the OGS, I went to a session about the future of Lotus Domino. Not a lot of exciting news, but there were a couple interesting things mentioned.

Improved NSF quality and recovery, the ability to save script libraries with errors, class browser, improved performance of XPages, improved usability in DDE, new components in DDE; outline, menu bar, tool bar and tag cloud.

They didn't specify a date on these improvements. Some of them should be included in the 8.5.1 release.

More sessions to attend.. Busy busy.. :)

Sunday, January 18, 2009

New LS/Java Editor coming in Notes/Domino 8.5.1

Writing my previous post, I missed the session I had planned on going to, "Getting to know XPages and the new Domino designer" (it was full by the time I arrived), I instead went to a session named "Introducing IBM Lotus Domino Designer 8.5 Now with Eclipse!".

There, they showcased the new editors for Java and LS. The LS editor looks promising, but the Java editor looked a little bit clunky usability-wise. The reason the new Java editor didn't appear in the current Notes release, 8.5 apparently has something to do with how Java code is stored in the NSF. IBM seems to have found a way around this, and in N/D 8.5.1, we will have the Eclipse Java editor for Domino Java code.. Good news! :)

They also skimmed the surface on what you can do with XPages. It seems like a quantum leap in flexibility above what you can do with the "old" Domino applications. Hopefully I'll make it in time for the next XPages sessions.

I didn't get the planned release date for 8.5.1. Not sure if they mentioned it/know when it will be ready.

Now I'm going to the a session about Cloud Computing with Bob Balaban. Could be interesting.

Day 0 of Lotusphere - Getting there

So the day started of well. I reached Sola airport in Norway an hour before the flight. I had plenty of time, so I read a little.

The first part of the trip went well. Sola - Copenhagen, no problems.

At Copenhagen, there were a few difficulties.

When I was boarding the plane, the jet engine was runnin at full speed, or so it seemed. When I got settled in, the captain let us know that there was a leakage from one of the engines, so the flight engineer had to repair this. Should only take fifteen minutes or so (he thought).

Fifteen minutes later, another message. The engineer wasn't able to fix the problem, so he had to get a new part. It should take about 45 minutes to fix. 45 minutes later, the engine was ok, but the driver of the car that was going to move the plane had gone home (resulted in an ironic laugh from all the passengers).

About 75 minutes over time, we finally got off the ground.

Around an hour late, the plane arrived at Washington. This was the part I feared the most. I'd heard a lot about US customs, and how strict they were. Maybe I was lucky, I don't know, I had no problems getting into the US. There were a lot of people waiting to get in, so that maybe resulted in the customs agents spending less time per person.

Then it was off to Orlando. Everyting went well. At this part of the journey, I felt totally lost, but somehow I found the places I needed to be. The last part of the journey was enjoying kids arguing with their parents for half an hour, while waiting for the bus to the hotel. All in all, I felt the trip went quite well.

Off to the first XPages session!

(this was written in a hurry, so please excuse me for any spelling mistakes)

Friday, January 16, 2009

Shipping off to Orlando

Tomorrow (Saturday) morning, Norwegian time, my plane leaves for Orlando and my first Lotusphere. Hopefully I've remembered to pack everything.

Just in case I need to be formal, I've packed a suit. Unfortunately, the tie was undone, and I don't know how to tie a tie. A few years ago, I'd have to ask a relative to tie the tie for me, but in this information age, all I needed to do was to go to youtube and do a search.

In case you also don't know how to tie a tie, here's how:


I'd hoped to arrive in time for B.A.L.D., but looking over my plane reservation, I see that I won't arrive at Orlando before 8pm.

But still.. Lotusphere! :)

My first bug found in N/D 8.5

When you're working with an application in the new Domino Designer, and open/close the application in the Client, the QueryClose event doesn't get fired.

I had to close DD to get the event to fire. This probably isn't the most serious bug, but it is annoying when working with/testing QueryClose.

Bugreport

Thursday, January 8, 2009

Use "nsd -kill" when killnotes doesn't work

Today, I got a "Shared memory error" after the Notes client crashed.

KillNotes didn't clean all the processes. This resulted in not being able to start Notes again. I did a little search, and found the solution.

I created a small bat-file that executes the NSD-command. If you want to use it, you probably have to change the line that has the path to Notes, "cd \Program Files\lotus\notes\" to fit your environment.

Wednesday, January 7, 2009

Useful new LS-method in Notes 8.5 - NotesDocumentCollection.StampAllMulti

Input parameter, NotesDocument. Add the values you want to stamp the collection with as fields in a (temporary) NotesDocument.

E.g.
Dim s As New NotesSession
Dim doc As New NotesDocument( s.CurrentDatabase )
Call doc.replaceItemValue( "field1", "1" )
Call doc.replaceItemValue( "field2", "2" )

'col is a NotesDocumentCollection
Call col.StampAllMulti( doc )