The code that is linked to above is a LotusScript class called SelectedDocsList. This class provides a way to programmatically access the list of selected docs in a view that's currently open in the Notes client (open in any tab, frame, or as an embedded view), without relying on an agent to be running against "Selected docs" in a view.
I originally wrote this class to get a handle on the docs that were selected in an embedded view on a page or form. Please note that it does not seem to work on embedded views that have a selection filter applied -- I have no idea why. Please see the code itself for more comments and information.
Someday I may write a database that demonstrates the code in action, but not today. In the meantime, I included a short bit of example code in the comments -- with the right view name, that can be used in an agent, in a button on a page or form, called against an embedded view or a view in the current window or a frame or a background tab or whatever.
It consists of a Java library I wrote called ZipFileManager, and some examples of how you can call it from LotusScript (using LS2J) in order to do things like:
The Java class itself is really mostly a wrapper around the Zip file functionality that's already built-in to Java, but it allows you to do things with a lot less code and a lot less understanding of the relationship between ZipFile and ZipEntry and ZipOutputStream and everything else you have to use. Also, it allows you to modify existing zip files, which is not natively possible with the Java classes -- again, no magic from me, just hiding all the temporary files and renaming you have to deal with.
There are only a few example agents in the database (no pretty forms or views). They are:
The examples are all in LotusScript (because that's what most people seem to understand), but it's trivial to move the code over to Java if you're so inclined.
All of the comments and explanation about the code are either in the agents themselves or in the JavaDocs that are packaged with the ZipFileManager JAR file and source code, which is included in the zip file that contains the database and is attached to the "About this Database" document as well.
I was actually going to add more examples and commentary in the database itself, but then I thought to myself "Who am I kidding? I've got another holiday weekend coming up!" So I left it like I left it. If you read this blog, you're smart enough to figure things out for yourself.
First, many of you will probably be asking, "What the heck is a singleton?" A singleton is a classic design pattern that allows you to make sure you have one and only one instance of a given class. So no matter how many times in your code you have something like "Dim blah As New MyClass", every new instance of MyClass that you create will all point to the same object reference.
Okay, that's great. But why would you want something like that?
Normally, you don't care about such things. But let's say your class is acting as a cache -- any kind of cache, really: database connections, view handles, messages, whatever. Within your code, the cache doesn't do much good if there are multiple instances of it, because then all the efficiency from caching goes out the door.
The typical way to solve this is to create a global Public instance of your cache class and tell developers to only ever use that one global instance. If you're particularly thorough, you'll even document that somewhere, probably in the code.
But here's the problem: some developers don't listen and don't read.
Essentially, the problem with the global instance is that it's fragile. It's built on trust. It relies on developers to know about the global instance and never use anything but that instance. In the case of a simple cache class, not using the global instance could cause inefficiency, but it's not that big of a deal. In other cases (like external database transactions), you might want to really make sure that all the code is using a single instance to keep things from breaking.
My original solution to this was to create a Public wrapper to a Private class, and any time the Public wrapper class was instantiated it would get a handle to a Private global instance. Doing it that way required the wrapper class to have a wrapper method around every method in the Private class, though, which was kind of annoying.
Then I asked a few people about it, and Bill Buchan mentioned that you could return an instance of a Private class as a Variant, and still make all the calls you wanted to the methods of the Private class.
This sounded pretty strange -- because anything outside of the Private class' agent/library isn't supposed to be able to see the class at all -- but I tried it and sure enough it worked.
So it turns out that you can declare a class as PRIVATE in a script library, and it's not accessible outside the library. However, if you have something inside that script library (a class method or function) that returns an instance of that Private class as a VARIANT, then suddenly you can call all the methods of that PRIVATE class and use it just like it's a regular Public class.
The downside (as Bill pointed out) is that you lose any compile-time error checking in your code. The upside is that it keeps people from creating multiple instances of your singleton class, which is the whole point.
UPDATE: Mikkel Heisterberg had some more to say on this subject as well. Follow the link for further discussion.
As an aside, Amichai seems like a really nice person. He actually gets regular e-mails from Notes users who ask him how my agent works. He always forwards the requests on to me very pleasantly, and is helpful when he can be. Please take note of the "donate" link on his JTNEF download page if you find the Extract Winmail.dat agent useful -- it wouldn't work without all the magic code he wrote and made available.
On a related note, there was an entry on the IBMEye blog recently that said:
For example, ask someone from Australia about the "date picker" component found in many applications that use calendars and you are bound to get a snicker. This term is used in the Lotus Notes documentation. I'll keep it clean and not elaborate here.
I just had to find out what that was all about, so I sent an e-mail to Brendon Upson (of Puakma and Booster fame), and he promptly responded that "date" was Aussie slang for "ass". Ahhhh... So a "date picker" would be used to pick...
Known Issues: Unable to capture images of movies in WMP or Winamp. This usually applies to all screen capture programs. It's hardware acceleration / hardware video overlay that causes it. In Windows Media Player, under the performance tab, slide the video acceleration to something less than full. In Winamp, under Video Options, uncheck 'Allow hardware video overlay'. This should allow you to take screenshots with any program.
Another mystery solved. I always thought it was just another Hollywood conspiracy.
I really did spend a very small amount of time doing this, which means I just dumped the video into Windows Movie Maker and clipped around the intro segments. Fortunately for me, this was quick, easy, and free. Unfortunately for you, the resulting file is a bit fuzzy and it's in WMV format.
If you're on a Mac and can't view it, this MacWorld article indicates that there's a really cheap Quicktime component you can install called Flip4Mac that will do the trick. If you're on Ubuntu like me, you'll need to apt-get w32codecs (you may have to adjust your sources.list to find it, I can't remember).
Each clip features the bad guy who is in that particular episode, so the evil magicial and the green curly afro dude aren't really regulars.
That site is going to have some really great stuff on it (no pressure Craig :-). You might recognize his name as the one behind the LotusScript ScriptBrowser tool that was released earlier this year.
He's already got several little freebie tools available for download, and apparently there are more on the way. LSCalls is especially useful for checking and auditing code, but I'll wait for him to talk about it before I put in my 2 cents. Just go out there and try it.
I put a video on for the kids tonight while we were making dinner, so they wouldn't be tempted to break anything while my back was turned. A quick look through the DVD collection and we settled on ElectraWoman and DynaGirl:
Does anyone else remember that show? Or the other Sid and Marty Krofft shows, for that matter? The DVD also had some quick trailer shots for other Krofft creations, like:
I think Dr. Shrinker was one of the old Krofft shows too, although I'm not quite sure. Too lazy to Google right now...
Anyway, I love these kinds of shows for the same reason I love the old Rankin/Bass "Animagic" Christmas specials. There's something pure in their cheesy goodness. For example, here's ElectraWoman and DynaGirl zapping a bad guy with their ginormous wrist scanner thingies:
Now that's good stuff. What's even funnier is when they're walking around as their alter-egos (i.e. -- wearing regular clothes instead of shiny superhero costumes), they still have those big honking wrist things on. Take a look:
Maybe in the 70's that was in style and no one would have noticed. I dunno, it's hard to remember.
Here are a couple other screen captures from the show, to bring back more vivid memories:
Sorry about the fuzzy car picture. I spent about 30 seconds scrolling around trying to find a more in-focus shot of their little spaceship-looking car, but I guess it just moved so darn fast it always turned out blurry. You get the idea anyway.
Funny thing is, the kids absolutely love taking medicine. They ask for medicine during the day, and jump up and run to the kitchen when it's finally time to take it. That's true for the the decongestant as well as the antibiotics. I've even tried the kid's cough medicine before, and it tastes just like grape juice.
What I can't figure out, though, is why adult medicine still tastes like crap. My wife got some "grown up" cough medicine the other day, and it was disgusting. If they can flavor the stuff to taste like juice and bubble gum for kids, why can't they flavor it up for adults too?
Here are some of the medicine flavors I'd like:
Anyone out there work for a drug company? Someone needs to actively market this idea.
Unbelievable. And it would have been impossible if the source code wasn't available for other people to look at. People talk about how open source is nice for the user, because they can go in and make changes/fixes by themselves if they want. But it sure is nice for the developer too, for the same reason.
So go ahead and use this link to reinstall the LDDMonkey script:
If Greasemonkey is already installed on your system, you can just right-click the link in Firefox and choose the "Install user script" option. Also, for reference, here are a summary of the changes that were made in this version:
version 1.6 -- December 3, 2005
LDDMonkey stopped working when Firefox got upgraded to 1.5. Kurt Higley (http://www.higs.net) fixed it within a day! His changes included:
* expander.onclick = ... changed to expander.addEventListener('click', ...)
* calls to XMLHttpRequest changed to GM_xmlhttpRequest
* restructure getResponseText() function to split it out a little better
I made a few changes to the URL processing, but otherwise included the changes as-is. Thanks Kurt!
I also added "https://*.lotus.com/ldd*" to the @include list for when you're logged in to the forum, and made it possible for the script to try to reload a response message if an earlier attempt never returned anything (which seems to happen at times).
Tested with Firefox 1.0.7/Greasemonkey 0.5.1 and Firefox 1.5/Greasemonkey 0.6.4
If you have no idea what this LDDMonkey thing is all about, please read this blog post to clear things up.
UPDATE: if you get a "file not found" error trying to install the script with the newest version of Greasemonkey, please read the Known Issues section of this blog entry on the GreaseBlog site for a possible workaround.
Well, first one of my co-workers told me that there's a little config hack you can make that will allow you to run old extensions on the new Firefox. Coolness.
Then I saw that they released a new version of Greasemonkey that works with 1.5, and I figured that was the "right" way to do it.
So I updated Greasemonkey, restarted the browser, reloaded the LDDMonkey script, and went to the LDD forums. And...nothing. It didn't work.
After a fair amount of troubleshooting, I found that the script was erroring out on this line:
expander.onclick = doExpander;
When I comment out the line, everything else seems to work, but that's the line that provides all the functionality. That's the line that makes the little [+] links actually do something when you click them.
At this point, I'm not sure if the fault lies with Firefox (new DOM quirk?) or Greasemonkey (some security thing?). So I'm trying to figure the whole thing out. I'll let you know.