Friday, August 14, 2009
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.
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:
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;
}
}
Labels:
random tip
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.
Labels:
mootools
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.
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.
Labels:
accessibility,
web
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.
I updated the code, so that the class aggregates the values into acomma separated string dynamic array. Single value parameters are still Strings.
>> The class in a txt-file
Share and enjoy!
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
Dim request As New HttpRequest()
Print Join( request.parameter("user"), "," )
' Prints tom,jane,jack
>> The class in a txt-file
Share and enjoy!
Labels:
web
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.
>> Bugreport
--
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
Labels:
Lotus Notes