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.