The View free online?

During the cleanup of my paper library with the View magazines I noticed that a lot of articles, including the PFD’s, of The View are indexed by Google and available online. I am not sure if this is a mistake or a seasonal gift from Wellesley Information Services but if you search online most of the older articles appear in the search results.

Older? “What is their use?” you may wonder. Most techniques described are obsolete or a sin, but others are so general (performance, programming best practices) or describe the core (2)of Notes that they are still interesting and fun to read.

Education is the most powerful weapon which you can use to change the world.

In case you wonder how to obtain the titles of the articles that WIS has published you can check for example this site.

Some search tips:

  • Enter titles case sensitive.
  • In case the PDF file does not appear in the results add ‘PDF’ as keyword or use Google Advanced Search where you can specify file type.
  • The locations VOLR6.nsf or viewr5.nsf are pretty unique keywords.

LotusScript equivalent for @Command TextSetFontColor?

In an form I have an action button:

changetext

Unfortunately this TextSetFontColor command only allows these colors:

  1. Black
  2. Gray
  3. Red
  4. DarkRed
  5. Green
  6. DarkGreen
  7. Blue
  8. DarkBlue
  9. Magenta
  10. DarkMagenta
  11. Yellow
  12. Brown
  13. Cyan
  14. DarkCyan
  15. White

In the Help file it says:

Language cross-reference
NotesColor property of LotusScript NotesRichTextStyle class

Is there anyone who has written the LotuScript equivalent to change the color of selected text in a rich text field (with RGB value)?

FindFirstElement(RTELEM_TYPE_TABLE) not always working

We have a rather large instalment base of a Notes application to publish webpages. Documents are created in Notes and viewed in a web browser.

From a user perspective it is quiet normal to select content from a website and paste it in Notes. Sometimes the number of nested (more: nasty) tables get’s too large and the document can not be opened anymore in Notes.

I am no expert in rich text but there seem to be some LotusScript methods available to read/write to rich text. For example FindFirstElement:

Moves the current position to the first element of a specified type in a rich text item.

You can supply a parameter, the type of element you are looking for. In my case this would be RTELEM_TYPE_TABLE

So my plan was to navigate through the whole rich text, count the number of  tables, present a dialogue to the user and ask which table(s) may be deleted (in order of appearance in the rich text).

So without removing the complete rich text the user has at least a way to re-cover parts of the document (I notice attachments do not get deleted when calling the remove method on a NotesRichTextTable, as a remove method on a NotesRichTextItem would do).

You can read more details in the Designer help. Look for:

NotesRichTextTable class > Remove method

All nice but during test I noticed some odd behaviour:

  • The method initially could not find ANY table in the rich text:

Messagebox “Body item does not contain a table,”,, “Error”

  • After I attached a file in the table the method seem to be able to discover tables.
  • When I copied the agent from one application to another application it seems to have lost its ability (again) to find elements in rich text . The step to attach a file in a table does not work here.

I also noticed that the method described in previous versions was called getfirstelement, this seems to be renamed in later versions (I am working with 8.5.2).

So I am left in doubt. Surely this is not something I can offer as a function to try to recover rich text.

  • Do you have an alternative approach you can recommend?

Nest-y tables in Lotus Notes

Today appeared an incident on my desk. A customer has problems with the number of nested tables in a rich text field.

It is unclear how they landed in the situation because if I nest some tables in my mail I get the warning:

Nevertheless the customer has a problem that needs to be fixed so I wonder what my options are?

  • Copy the rich text in a memo document and hope for the best that the number of nested tables is equal or less than the maximum number of 8
  • Find a tricky way to navigate through the rich text, grab the table with more than 8 levels and cut off a couple of layers of nested tables untill the maximum number and copy it in a memo document

I guess the last approach is the best one, but the most complicated.

How do you handle exceedings of nested tables?

Link of interest: Idea on IdeaJam.

Buggy LotusScript debugger – Looses focus at startup.

Whenever I start the LotusScript debugger it comes up and then disappears. It simply loses focus.  I cannot set focus on the debugger via the tab controls under Windows. What is worst, Domino Designer also becomes frozen, since it is said to the background by the debugger.

Have more people experienced this pain and how did you solved it? Can it be resolved by any of the preferences in Designer under debug?

I read a similar case here. I have registered a support case at IBM so I am waiting for a reply. But in the mean time I cannot test my code…

PutInFolder method – does not allocate my private folder

For a search function in an application I would like to place results in a private (desktop) folder. For that I created a shared, private on first use folder. I do not want to have a folder residing on the server side because I fear this will blow up the view indexes. It is also a restriction in our environment (create personal folders is by default disabled).

The private folder will be created when opening the search form which is embedded in a split frame (on top the search form, in the bottom the folder).

However when I use the PutInFolder method, this tries to place result documents in the first folder it finds, in this case the shared, private on first use folder.

Call srchDoc.PutInFolder(“$fld-searchresults”)

This is also confirmed via a warning message:

If I look in design it seems the method wants to place the documents in the first folder it finds:

AddToFolder

On the other hand, when I have a document opened the AddToFolder formula has no problem with finding the correct folder:

@AddToFolder(“$fld-searchresults”;””)

Question

My question is quiet simple:

How can I make sure that my code places the documents in the private folder and not the shared one?

XPages and WQO agents – Cardscan app

I would love to rebuild my Cardscan integration application with XPages and make it an OpenNTF project, the only BUT is  that the transfer of the data that comes from Cardscan is done via a WQO agent in LotusScript.

I wonder if there are examples out there that proof it IS possible using WQO agents in XPages? It would save me a hell of a time and probable if it is not possible I would not do the transformation of the app att all (I am not a Java guy).

So hints/demo/code etcetera are welcome…

jQuery TreeView Menu from Notes View

I was looking for a way to get a web publishing toolkit in Notes away from displaying documents in a frameset.

The frameset consists of several frames:

  • a header section
  • a leftside navigation section
  • a main or content section

The reason why a frameset is used because the leftside navigation is populated from documents in a Notes View.  This navigator would be collapsed again every time it would be re-loaded again.  It is also build by an agent that generates XML which needs to be transformed in the browser.

Here is how it looks today:

nav_current

Some searching on the web brought me to these documents:

jQuery TreeView Menu and a Show ‘n Tell Thursday blogpost. Combining the 2 topics would solve my problem since the jQuery TreeView allows to re-open the treemenu by the location specified for a menu item!

( I will add the SnTT tag to this document to honour the contributors, even when it is now still Thursday)

I soon discovered that the code for the Tree Convertor from Datatribe works with documents in the same level, meaning that documents with a response hierarchy will not be supported because you do not use categorized columns in your View. Nevertheless a little trial and error and rewriting the original code resulted in the following Notes View presented as a tree:

nav_new

Note: in the example I have already applied some styling.

In this View each ‘Category’ is a document containing one or more response documents. The highlighted (red) item is the currently opened document.

So how do you get there?

  • Create a Notes View that displays your documents as you want them to be presented in the tree. In the Datatribe example this View is called (LUDocs).

nav_notesview

  • Upload all the fields you need for the jQuery TreeView (CSS, Images, JS Libraries) and reference to them in the Head section of your Document Form:

nav_header01

  • Add the fuction that will transform the HTML list into a Tree View structure.

nav_header02

Note:  -the persist: “location”- parameter ensures that the tree will be expanded by the item / document opened by default.

  • On the place where you want to display the TreeView add the following code:

nav_new_code

As you can see a script is here called which uses an Agent to collect the data from a Notes View in an HTML format ( ul and li list format). I had to make come changes to the original code, since I am using a View that support the display of response documents in a hierarchy.

Sub Initialize
‘—This agent is designed to ouput the required javascript to produce a nested HTML list
On Error Goto errorhandler

Dim s As New notessession
Dim db  As NotesDatabase
Dim doc As NotesDocument

‘–Category passed in via URL
Dim inCategory As String

‘—View name passed in via URL
Dim viewName As String

‘—Display Category ?
Dim displaycategory As String

‘—Document in the view
Dim tmpdoc As notesdocument

‘–Category Level
Dim level As Integer
‘—Current Category level
Dim currentLevel As Integer

Dim view As NotesView
Dim i As Integer
Dim JavascriptOutput As String

‘—Due text size limits we need to hold the ouput on 1 or more temporay notes items (never saved)
Dim fieldCounter As Integer
Dim holdingField As Notesitem

Set doc=s.documentcontext

‘–Set up holding field
fieldCounter=1
Set holdingField=New notesitem(doc,”HoldingField_” & fieldCounter,””)

inCategory=getqueryparam(doc.query_string(0),”category”,””)
viewName=getqueryparam(doc.query_string(0),”viewname”,””)
displaycategory=getqueryparam(doc.query_string(0),”displaycategory”,””)

Set db=s.currentdatabase

level=0
JavascriptOutput=””

If displaycategory=”false” Then

Else
If inCategory=”” Then
JavascriptOutput=JavascriptOutput & |<h3>All Documents</h3>|
Else
JavascriptOutput=JavascriptOutput & |<h3>| & inCategory & |</h3>|
End If
End If

JavascriptOutput=JavascriptOutput & |<ul id=”tree”>|

‘—-View could be passed in via QueryString to allow a more generic agent
Set view=db.GetView(viewName)

‘—If view is not found handle it – as the view name is passed in this could be missing
If view Is Nothing Then
Print |Content-Type:text/plain|
Print |document.write(‘Error – View not found -| & viewName & |’)|
Goto getout
End If

Dim entry As NotesViewEntry
Dim nav As NotesViewNavigator
If inCategory=”” Then
Set nav = view.CreateViewNav
Else
Set nav = view.CreateViewNav
End If
Set entry=nav.GetFirst

Dim edoc As NotesDocument
Dim childdoc As NotesDocument
Dim coll As notesdocumentcollection

While Not(entry Is Nothing)

Set edoc = entry.Document
Set coll = edoc.responses

If coll.Count > 0 Then
currentLevel=entry.ColumnIndentLevel+1
Select Case (entry.ColumnIndentLevel+1)
Case level
%REM
JavascriptOutput=JavascriptOutput & |</ul></li>|
%END REM
Case Is<level
For i=2 To ((level)-entry.ColumnIndentLevel)
JavascriptOutput=JavascriptOutput & |</ul></li>|
Next
End Select

‘–Update level
level=entry.ColumnIndentLevel+1

‘–Propercase it
JavascriptOutput=JavascriptOutput & |<li><strong><a href=”http://| & returnCommonServer() & |/| & swapchars(db.FilePath,”\”,”/”) & |/0/| & entry.UniversalID & |”>| & edoc.Tx_Document_Title(0) &|</a></strong><ul>|
Else
‘—At document
currentLevel=entry.ColumnIndentLevel+1
Select Case (entry.ColumnIndentLevel+1)
Case level
%REM
JavascriptOutput=JavascriptOutput & |</ul></li>|
%END REM
Case Is<level
For i=2 To ((level)-entry.ColumnIndentLevel)
JavascriptOutput=JavascriptOutput & |</ul></li>|
Next
End Select

‘–Update level
level=entry.ColumnIndentLevel+1

Set tmpdoc=db.GetDocumentByUNID(entry.UniversalID)
Set tmpdoc=entry.Document
If tmpdoc.Tx_Document_Title(0)<>”” Then
JavascriptOutput=JavascriptOutput & |<li><a href=”http://| & returnCommonServer() & |/| & swapchars(db.FilePath,”\”,”/”) & |/0/| & entry.UniversalID & |”>| & fn_escape(Cstr(tmpdoc.Tx_Document_Title(0))) & |</a></li>|
End If
End If

‘–Check for field size
Call holdingfield.appendtotextlist(JavascriptOutput)
Call monitorFieldSize(doc ,fieldCounter,holdingField)
JavascriptOutput=””
Set entry=nav.GetNext(entry)
Wend

‘–Now we have finished we need to close the remaining tags
For i=1 To (currentLevel-1)
JavascriptOutput=JavascriptOutput & |</ul></li>|
Next

Call holdingfield.appendtotextlist(JavascriptOutput)

‘—-Now output Javascript

Print |Content-Type:text/plain|
Print |document.write(‘\n’+|
If fieldcounter=1 Then
Forall items In doc.GetItemValue(“HoldingField_1”)
Print|’| &  items & |\n’+|
End Forall
Else
For i=2 To fieldcounter
Forall items In doc.GetItemValue(“HoldingField_” & i)
Print|’| & items &  |\n’+|
End Forall
Next
Forall items In doc.GetItemValue(“HoldingField_1”)
Print|’| & items  |\n’+|
End Forall
End If
Print |’\n’)|

getout:
Exit Sub

errorhandler:

‘—As this is an agent that expects to return JavaScript we will return the error message in Javascript
Print |Content-Type:text/plain|
Print |document.write(‘Error – | & Error & | – | & Err & |’)|

Resume getout

End Sub

That is about it! Here is a better look of the result:

nav_result

Pagination on a View in the Notes client

A problem with Notes Views is that when they contain a lot of documents scrolling becomes inevitable. Even when you apply categorized columns it will become necessary that users click through the Views. An option would be that you just start typing and hopefully Notes will lead you to the nearest corresponding document.

When you apply categorized views the categories are displayed vertically below each other so for travelling users with smaller screens it will become tasly to open and close the categories just to see thse categories and corresponding documents displayed in a properly in the overview.

Maybe XPages in the Notes client will bring us some relief, but we are not there yet.

So how do we cope with the issue for the time being?

On the web it is common practice to have some sort of pagination on top / below lists of documents so you can navigate through the list without the need to scroll up and down or move you mouse across the screen. The pagination can be based on number of available pages or just available short cuts (example: the first letter of an available lastname). I myself have written some articles about pagination on this blog which you may check out yourself.

So this is all about the web, I adress this article to pagination in the Notes client.

The simplest way I found is to create a list of similar shortcuts, containing javascript, and render pass thru HTML in Notes. In this example I explain how I added pagination to a list (a Notes View) of persons. The thought is to show a list of persons form which their lastname start with a certain letter. What I needed to accomplish this:

  • A Form with an Embedded View. This View should be categorized by the first letter of the lastname @LowerCase(@Trim(Tx_LastName);1). SaveOptions are set to zero ofcourse.
  • The Embedded View has the ‘Show single category option’ in use.  As formula write the name of the Field that will acts as a temporary container (Tmp_LastName).
  • Add a Field named TmpLastName on top of the Embedded View. Make it editable. As default value give it the value “a” (you could check if this value is really available or not).
  • On top of the Form add the following JavaScript and CSS code:

<script language=”Javascript”>
var entryNumber = “”;
function showTab(lastName) {
entryNumber = lastName;
document.forms[0].LastName.value = entryNumber;
entryNumber = “”;
document.forms[0].set_field.click()
}
</script>

<style type=”text/css”>
font {
font-family: “Default Sans Serif”, sans-serif;
font-style: normal;
font-weight: normal;
font-size: 8pt;
color: black;
text-decoration: none;
text-align: left;
text-indent: 1ex;
}
A:link {color: blue; text-decoration: none}
A:visited {color: blue; text-decoration: none}
A:active {color: blue; text-decoration: none}
A:hover {color: blue; text-decoration: none}
</style>

  • As final step you need to add a computed text just above the Embedded View. Mark the text as passthru HTML. A Value enter:

varList:=@DbColumn( “”: “NoCache” ; “” : “” ; “PersViewCategorized” ; 1 );
tmpList:=@Implode(“<a href=\”javascript:showTab(‘” + varList + “‘)\”>” + varList+ “</a>” + ” | ” );
@LeftBack(tmpList;”|”)

Here we make a call to first column in the same Embedded View. Around each found category we wrap a JavaScript call which will put the value in the temporary field and finally we call the button to update the UI.

Here is a screendump that shows how it could look like:

paginationNotes

A problem discovered

Well everything  looked shiny untill I tried to load the Form in a Frameset. When pressing on one of the links I got the message:

paginationNotesMessage

Some work to do IBM….