Taking Class-Based LotusScript A Step Further
Getting in to this whole class-based LotusScript malarkey I was thinking about how to take the HTMLArea class forward and realised the possibilities are almost endless. Imagine:
myArea.addParagraph(text)
Which would be the same as
myArea.add("<p>"+text+"</p>")
Or how about
myArea.openTable(optionalParams)
myArea.addTableRowFromArray( item.values )
myArea.closeTable()
That's all for some other time though. Next on my list of things to do is create a WebSession class. Just about every single agent I write starts with the same six lines of code:
Dim vWebSession As NotesSession
Dim vThisDatabase As NotesDatabase
Dim vWebDocument As NotesDocument
Set vWebSession = New NotesSession
Set vWebDocument = vWebSession.DocumentContext
Set vThisDatabase = vWebSession.CurrentDatabase
Every time I create a new agent I find myself looking for another one that I can open and copy these six essential lines of code from. What I'd rather do is store them in a separate class (in the pervasive "CommonRoutines" library), so that I can easily create and initialise them all with one line of code, like this:
Dim wSession as New WebSession()
From there on in I can code like this:
msgbox wSession.commonusername
msgbox wSession.database.title
msgbox wSession.document.univeralid
set view = wSession.database.getView("this")
I'm assuming this is a) possible and b) easy to do, but am wondering if it's advisable or been done before — meaning I can just copy the code and save myself some time. Guys?
I once wrote for a customer project a library which basically did this. It was in java though.
I implemented a Request object and a Response object, alike ASP.NET. Request contained methods like getCookie, getParameterValue, getAuthenticatedUser (which in turn returned a 'UserObject'), etc. etc., Response contained methods like setCookie, a setContent method to write output, a setContentType method, a Redirect method, etc. etc.
I went a few steps further and implemented it using a 'controller' agent, which executed classes on the fly based on a parameter in the URL. The 'controller' agent took care of initializing the objects and handed them over to the class that actually ran the logic I wanted to execute.
So it's been done before, it's possible, but unfortunately I can't provide you with the code...
I wrote a while ago about it on my weblog: {Link}
It might be an idea to "layer" the classes, so the base class did simple HTML, the next class up handled DIV sections, CSS, etc.. (warning: random architecture on the fly - might not be relevant!)
the nice thing about this stuff of course is that looking at the blogsphere source code (for instance) is that there's ooodles of commonality herre.
And of course, switching between HTML and/or XHTML for instance can all be hidden from the consumer...
---* Bill
Hi Erwin. Long time! Thanks for link.
Hi Bill. I don't see myself creating DIVs or CSS. The way I envisage HTMLArea to be used is for snippets of code inserted in the already-laid-out page of HTML - created by Domino subforms and fields etc. It's only intended for low-level HTML element addition.
Anyway, "layering classes"? Come on. I've barely got to grip with an unlayered class!
I think such a class is a great idea... my own similar one is called HTMLEmitter.
The hard thing is finding time to implement it, when competing with other priorities. Its great to -have-, just not easy to invest time into utility classes of this nature.
If I was to readdress my HTMLEmitter to do the syntax automatically as you have outlined, I would have it create an internal stack of elements pending that require closure, and provide graceful errors if you close them incorrectly. This would probably save a LOT of time correcting the emitted HTML!
Based on what you've now described, I'm envisioning an entire framework of derived classes that allow actual DOM manipulation: HTMLArea.createElement("p"), for example, would return a new HTMLParagraphElement, which would derive from HTMLElement. HTMLArea and each class deriving from HTMLElement would have a .appendChild method, allowing elements created out of sequence to be inserted where appropriate. When the entire DOM is constructed, HTMLArea.renderToField("fieldName") would traverse the structure and write the entire stream to the rich text.
Probably more work than it'd be worth, but this would allow more flexibility in how the content is obtained.
yeah, i've got some code sorta like that. not the same nomenclature, but the same basic idea. pretty much what tim describes.
i'll post it today or tonight, when i get a little time.
i love lotusscript classes. i'm a bit of a freak about them actually, although not the expert that wild bill is. anyway...
Hi Jake, well, in my AXE library I have included some code like that to initialize some globals variables that I used across the LS Libraries, routines and functions.
I'm planning a sort of webcast to show so I'll let you know.
.::AleX::.
Darn Lotus for not allowing us to SubClass NotesSession.
It would be a waste to add most of the functionality of NotesSession to WebSession.
Why call vWebSession.Document.UniqueID when you could just call Session.UniqueID?
Maybe a WebSessionTool(session as NotesSession) class would be more appropriate. It could have tools for the QueryString and server/database urls but would not replicate functionality from the NotesSession class.
I did something like your session class, but I did it differently. I have a base class model that instantiates all the session stuff and split the query variables and such in the constructor. Then I have a model_<form> for each form that inherits the base model. In these models I override the Open (for QueryOpen events), and Save (for QuerySave) events.
Now I don't have to worry with the constructor since its defined in the base. Some commonly used objects (like DocumentContext) are then exposed as properties in the base class.
This whole thing is dynamically loaded by 2 agents (1 QO and 1 QS) based on a field (so that it also works with view templates). It has worked very well for me :)
I have also been given the permission to release this as open source, so if you are interested, send me an email, and I will give you a copy.
regards,
Bjorn
I encourage you to check out Chad Smiley's work on his Domino Extended LotusScript Library:
{Link}
The beauty of the library is that it handles creating the handle to the class for you, so you can skip this kind of code:
Dim wSession as New WebSession()
Also, you can code the properties to be instantiated "on demand" instead of all the time.
Jake,
Not sure if you're aware of this (and I have not checked other postings since I noticed it myself a minute ago) but your Recent Comments section lists the comments as being "Over 3 years ago". None of these comments, nor the article itself, are over 3 years old yet. Just noticed this and thought I'd bring it to your attention. I don't know if it was just this posting or if it is an issue in other postings as well.. may have been something you noted yourself and fixed by now.
Hi Joel,
I hadn't noticed that. As a quick fix I made it say "about X years ago". The guilty line of code was:
"over " + Cstr(Round(difference_in_minutes / 525600, 0)) + " years"
I hadn't accounted for it rounding up!
Whether I'll make it more accurate I don't know. It's just meant as a very rough idea of when it happened.
Jake