Drop me an e-mail to get sample database.
Drop me an e-mail to get sample database.
It's quite common to use embedded view in notes application but many of Lotus Notes developers don't find easy and efficient for web based application.I was going through Notes/Domino 6 and 7 Forum and found similar problem to one of the developer. She wanted to display a combobox (which refers to docs in a view on the database) to show only selected docs in an embedded view. e.g. category = "Finance".
http://www-10.lotus.com/ldd/nd6forum.nsf/DateAllThreadedweb/b03202c47143f47b8525761e0067fe74?OpenDocument
She didn't got satisfactory answer so created another post saying , She wanted to refresh an embedded view based on the value of a combobox on the web.
http://www-10.lotus.com/ldd/nd6forum.nsf/DateAllThreadedweb/66a335842154b86c8525761f0060073b?OpenDocument
So question is why should we use embedded view in web based application ? , Does it really required ? Can't we achieve similar functionality using ajax ? Don't you think we should break the trend which was started in Notes 5 era ?
Actually I never used embedded view in any of my web applications.I prefer AJAX instead of embedding view because it's fast and interacting well to the end user.
Let's have a look to simple requirement where you've to provide List box to the user where he can select multiple orders and can view their details. There could be many ways to achieve this but what could be the elegant way to make users WOW .. It's AJAX.
Here is the sample,
Here are simple steps to get rid of embedded views in web applications,
Step 1: Create a single column lookup view with following column formula,
orderNo + "|" + @Text(@DocumentUniqueID) |
Step 2: Write dbcolumn in combo box to populate order numbers.
Step 3: On "View Order" button click write JavaScript to retrieve Document UNID and pass them to AJAX function.
//-------------------------------------------------------------------------------- var orderID=""; var sep=""; for(i=0; i<=document.forms[0].OrderSelection.length-1; i++) { if ( document.forms[0].OrderSelection.options[i].selected ) { orderID = orderID +sep+document.forms[0].OrderSelection.options[i].value; sep="^"; } } displayOrder(orderID); //-------------------------------------------------------------------------------- function displayOrder(orderID){ url= location.href; tmpurl = url.substring(0,url.indexOf(".nsf")) agentUrl= tmpurl+".nsf"+"/displayOrder?OpenAgent" argsParam=trim(orderID); runAgent(agentUrl,argsParam); } //-------------------------------------------------------------------------------- function runAgent(agentUrl,argsParam) { req = false; if (window.XMLHttpRequest) { try { req = new XMLHttpRequest(); } catch(e) { req = false; } } else if(window.ActiveXObject) { try { req = new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) { try { req = new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) { req = false; } } } if (req ) { req.onreadystatechange = processReqChange; req.open("POST", agentUrl, true); req.send(argsParam); } } //---------------------------------------------------------------------------------- function trim(str) { return str.replace(/^\s+|\s+$/g, ''); } //---------------------------------------------------------------------------------- function processReqChange() { if (req.readyState == 4) { if (req.status == 200) { document.getElementById("status").style.display="none" ; xmlStr=req.responseText if ( xmlStr == 0 ) { document.getElementById("status").innerHTML="Error in retrieving order"; return false; } else { document.getElementById("Contents").innerHTML=xmlStr; } } else {alert("There was a problem retrieving the XML data:\n" + req.statusText);} } } //----------------------------------------------------------------------------------- |
Step 5: In your Lotus Script agent use "Request_Content" CGI method to retrieve POST arguments. Write your business logic , Build custom HTML and return them using Print method.Don't forget to set content-type as per your logic ( Text, HTML or XML ). Code can be,
There are best ways to design Lotus Notes applications robust and as powerful as dot net and Java, Don't let others say "Notes systems are ugly".It's just our efforts which can lead Notes market as high as It was 10 years ago..
Recently I've got a requirement to build address picker for web application which uses Active directory.I've spend couple of hours on net to find some sample application/code but no success. Even though I had implemented ActiveX and JNDI based program which search users in Active directory but those were for Notes client based application.
After some case study , I came to know only solution is to write Java Servlet to connect Active directory and build address picker on the web.After reading some Servlet tutorial and Notes help file got some confidence in writing Servlet in Domino application.I must say, It was quite easy and fun to write Servlet program.Here is my address picker which works perfectly in IE and Firefox allowing multiple users selection.
Let's start some postmortem on the code. First check my core logic to connect LDAP and retrieve records.Probably it's same as which I've posted in my last blog
In above code, I'm looping through each person records in Active Directory and writing in the list box using PrintWriter class.
Now lets check the code in very simple steps.
Step 1: You need following classes to be imported in your agent,
import java.io.*; // For PrintWriter class import javax.servlet.*; // For Servlets class import javax.servlet.http.*; // For Servlets class import lotus.domino.*; // For Domino class import java.util.*; // For util import javax.naming.*; // For JNDI import javax.naming.directory.*; // For JNDI |
Step 2: Construct basic skeleton to write Java class.
public class namePicker extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException{ try { // Code goes here }catch (NotesException n) { System.out.println("Exception ID: " + n.id); System.out.println("Exception description: " + n.text); } finally { NotesThread.stermThread(); } } } |
Above code extends a Java interface called HttpServlet.Inside the code, there are a few predefined methods you want to override, for example, here doGet() method gets called with HttpServletRequest object and HttpServletResponse object as parameters. The HttpServletRequest is a java object that is created by the container and captures an incoming HTTP request in an object form.HttpServletResponse provide HTTP-specific functionality in sending a response. For example, it has methods to access HTTP headers and cookies.
Step 3: Using setContentType method to sets the content type which will be sent to the client.Next, Creating PrintWriter object from getWriter method of HttpServletResponse class.This class is used to write contents on the browser.
res.setContentType("text/html"); PrintWriter printOnBrowser = res.getWriter(); |
So our code will be ,
public class namePicker extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException{ res.setContentType("text/html"); PrintWriter printOnBrowser = res.getWriter(); try { //codes goes here }catch (NotesException n) { System.out.println("Exception ID: " + n.id); System.out.println("Exception description: " + n.text); } finally { NotesThread.stermThread(); } } } |
Step 4: Now we need to create NotesThread and initialize Domino session. To do so,
NotesThread.sinitThread(); Session session = NotesFactory.createSession(); |
Using sinitThread() method of NotesThread class and NotesFactory class to creation Notes session. Check designer help to get more idea.So our code changed to,
public class namePicker extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException{ res.setContentType("text/html"); PrintWriter printOnBrowser = res.getWriter(); try { NotesThread.sinitThread(); Session session = NotesFactory.createSession(); }catch (NotesException n) { System.out.println("Exception ID: " + n.id); System.out.println("Exception description: " + n.text); } finally { NotesThread.stermThread(); } } } |
Step 4: Now you're well set to write HTML and JavaScript in Servlet which will be printed on browser like Lotus Script "Print" statement. Something like,

Step 5 At the end don't forget to destroy Domino objects which you've created because we are using Multi threaded programming , mistakes can screw your Domino server. To destroy Domino objects, User recycle()
session.recycle(); |
How I'm calling my Servlet from Domino
window.open( '/servlet/namePicker','newWin', 'toolbar=no,location=no,directories=no,status=no,menubar=no, scrollbars=no,resizable=no,width=540,height=340') ; |
Note that I'm referring "Servlet" folder from my server directory which is in (Lotus\Domino\data\domino\servlet)

Full Servlet code can't be posted here because lack of HTML support on this site.If anyone interested in getting full code ,drop me an e-mail.Along with that I've done similar name picker which use NAB using Servlet.Hopefully soon both sets of code will be posted in OpenNTF.
Hope this article can be useful to those who wish to integrate Domino with third party application using Java Servlet.
Oops, Forgot to mentioned some links for those who are not sure how to run Servlet in Domino, there is some gotcha in that :). You may follow Jake's article ,
Creating servlets inside the Domino Designer
Java servlets: Extending your Domino applications
Only thing is changed from Jake's article about adding ,jsdk.jar in your agent . You don't need to do any more ( at least with Designer 8.5 )
Dojo made easier to build model popup window with blur parent.It can be easily achieved using dijit.Dialog.Dojo dialog box acts like a web form on a sticky note. By overlaying the view page underneath it, the dialog box can use room for more form
controls. First look into some cool examples which can be done using dijit.Dialog.
Let's see in simple steps,
- I assume before start you already have dojo set up in your machine.
- Create DIV tag at the end of your web form and specify dojoType as dijit.Dialog. Along with that add id and title tag to DIV.E.g,
- Next you need to design your HTML which you're going to display in dialog box. Let's say simple address popup box. E.g,
- Pleace your HTML inside DIV tag which you've created in first step. E.g,
- At the end call your dialog box on any event using show() method of dijit. E.g,
- Check the output ,
Yesterday I was working on Audit trail functionality for one of my web form. I was using Rich text field to log activities on the form. Code was quite simple so done in few minutes and started testing.Chunk of my code was ,
Call rtitem.appendStyle(RtStyle)
Call rtitem.AppendText(tmpname.common)
Call rtitem.AddNewLine(1)
When I've started doing testing found AddnewLine property doesn't work fine and giving strange results.
I've tried to debug but not able to find what is wrong with AddNewLine method which works perfectly in client application. Next, I've decided to use PassThruHTML property of NotesRichTextStyle class and insert HTML directly into Rich Text field. When I've started testing the new code found RT field is not parsing HTML correctly.
Even I've used the same code which is mentioned in Notes help but didn't work.
I thought there must be a problem in putting RT field in HTML table , so I took out and placed outside table and verified but no use. My next debugging was from dojo side , I thought there must be something which I might have missed in dojo. I've spend couple of hours to test if anything went wrong in dojo but ended up with the same problem. At the end started looking IBM articles and found it's known bug which is reported five years back. To work around this issue, add brackets, [ ], around your string.When applied this work around everything works well ,
http://www-01.ibm.com/support/docview.wss?uid=swg21097539
I've couple of concerns, First, Why this bug is still there with R8.x versions ? This must be fixed long time back or they don't like to enhance Rich text capabilities in Lotus Notes.Second, Why AddNewLine property doesn't work properly on web like Notes client.
Have you ever encountered initialization error in building dojo application? . Most frequent errors are ; dojo is not loaded,getElementByid("..")/dojo.byId("..") is null or not an object, dijit widget is not loaded etc etc. It's certain that there is something wrong in parsing HTML, but it's not as easy to rectify like traditional HTML web pages.
| Scenario |
You are using dojo.byId("..") or document.getElementById("..") on OnLoad event of the form and ended up with "dojo.byId("..") not defined or not an object" error. This is very common use of OnLoad event in Domino web applications.
Something about dojo.addOnLoad() |
Dojo's addOnLoad() makes sure that the DOM tree has been built by the browser and any other JavaScript that the handler references has been downloaded and evaluated.In dojo application we need to make sure that JavaScript resources that we’ve dojo.required and/or the DOM tree are ready for use.
What dojo.addOnLoad does ? |
dojo.addOnLoad takes a reference to a function and guarantees that the provided function is executed immediately after the following three conditions are met:
# The DOM tree has been built by the browser and is available for use by client code.
# All JavaScript resources demanded through the Dojo loader have been loaded.
# All Dojo widget parsing has been completed.Dojo lets you specify widgets directly in the HTML code. When you include Dojo widgets , Dojo must parse the HTML and replace each embedded widget with the actual HTML that implements the widget.
If djConfig.parseOnLoad is true, then this is accomplished as soon as the DOM tree is loaded by the browser but before any function registered with dojo.addOnLoad is executed.
| Facts in using dojo.addOnLoad() |
# dojo.addOnLoad can be used any number of times.
# Each function given as an argument in dojo.addOnLoad() will be executed in the order it was provided.
| Solution |
# Scenario 1 : Setting up value in variable(s) or pop-up alert to the user on onLoad event of the form.
Instead of ,
use like,
# Scenario 2 : Calling JavaScript function on onLoad event of the form ,
Instead of ,
use like,
# Scenario 3 : Attaching JavaScript function to any object on any event
( Note:JavaScript code is not allowed in the blog, write me for actual code )
To reference the Dojo Toolkit to our page usually we would do by downloading the source from Dojo web site and putting it on our own site then linking to it. We can reference the Dojo source files on the Internet without requiring us to have the source on our own web server.
AOL provides a facility it calls the Content Delivery Network (CDN), which is a
“worldwide geographic edge caching” mechanism for the Internet.This allows super fast delivery of files to web users from AOL servers that are geographically close to them.
The files are also compressed, which further improves the download speeds.AOL has
generously made this facility available to developers and end users. For more information on the AOL CDN and Dojo, visit http://dev.aol.com/dojo.
So just provide a link to the Dojo files on AOL CDN and do not need to download them to your site at all.
As I experienced ,Populating list box dynamically in HTML is not simpler than other HTML controls.However it's more complex when you use dijit FilteringSelect.FilteringSelect is like an HTML SELECT tag, but is populated dynamically. It works very nicely with very large data sets because it can load and page data as needed.
Actually,I have come up with the requirement based on the option selected in radio button drop-down should be populated from configuration document.E.g, We have radio button with three options ; A , B and C. Once you select A; country name starts with 'A' should be populated in drop down and Same as for B and C. When I visited Dojo site for some example found following,
But it was not as easy in implementation as shown. Lets see how it's done.
First, I kept three hidden look-up fields on the form to hold data from configuration document. Fields were , lkpA, lkpB and lkpC ; all three fields look-up country name starts with their corresponding initials.
Next, my JavaScript function which triggers on radio button (Where options A,B and C ) . Code actually pass the look-up field handle to another JavaScript function which actually populates the drop down. Code looks something like,
And here is populate_category function which actually loop through passed hidden field,builds JSON and populate drop down.
Would like to hear if it could be achieved more easily ;)
1 - Getting Started with XPages By Rob McDonagh
2 - Harness the power of XPages in Lotus Domino Designer By Chris Toohey
3 - New XPage Tutorial By Peter Janzen
4 - XPage Examples by John Mackey
5 - Learning XPages By Declan Lynch
Today while working on one of the requirement, I encountered strange thing about onChange event behavior in Internet Explorer 7 and Mozila Firefox 3.
Actually my requirement was to show and hide div based on the radio button selection. I was having following code on "onChange" event of the radio button,
Code was executing very well on Mozila and everything was fine, But same stuff was working unexpected in Internet Explorer. According to the code , DIV A should visible if "Yes" was selected else DIVB should be visible. When I ran the code in IE, On selection of "yes" nothing was happening , but on selection of "No" DIV A was getting visible which was wrong. However that's the way "onChange" event should work but why Mozila is showing correct DIV on onchange event. I didn't got the answer by myself or even from the Google.
After few attempts, I didn't put much attention and put the code in "OnClick" event of the radio and it works well in both the browser. Just forsake checked in Google , found many people experienced the same. Anyways I had other stuffs to do so left there it is..
Would love to know if anybody get the answer :-)
Recently in my new project I have implemented flash/xml based charts powered by (www.fusioncharts.com). Great thing is that it's free to download and use. You need to pay if you wish to go for advance charts.So, Lets discuss those which can be downloaded with no cost. There are number of charts like, 3D/2D Column & Bar Charts,Line Charts,2D/3D Pie & Doughnut Charts,Area Charts,Stacked Charts, Gantt Chart and many more. Have a look here,
(http://www.fusioncharts.com/free/Gallery.asp).
FusionCharts are .swf file which takes xml data as a input and draws flash charts on .For domino implementation just add swf file in your File Resource , build your xml string, pass it in the chart and get the nice flash chart.
Actually, I have been implemented this long back in PHP, but never got such requirement to do in Lotus Notes. But when I got the requirement , I consider FusionCharts only because it's simple and great.
In this blog I will discuss everything starting from form designing to displaying chart. I will be using Bar chart in this example.Let's start now..
1- We are going to display number of "Site visitors" by month. To do so , Add text field in your form A called "Site Name". In next row add caption start from "Jan" to "Dec" ( in separate column) and at the end "Total" caption. Now add one number field for each month and one for calculating "Total" for the year. Put a formula on "Total" field to calculate total ( Jan+Feb+..+Dec).Here is the visual,
2- Run your form in notes and create some sample docs by feeding entry for each month.Something like,
3- Create one more form B ,which will share the same form name as Notes form ( which used to create document earlier) which will be used to open the document on web with chart.here is the visual,
4- Open Form B in designer and add first text field (Computed for Display) called "ColumnChart" and write following formula,
tmpProtocol:= "http" + @If(HTTPS="ON"; "s"; "");
txGraphURL:= "FC_2_3_Column3D.swf";
tmpProtocol + "://" + @GetHTTPHeader("Host") + "/" + @WebDbName + "/" + @URLEncode("UTF-8";txGraphURL)
( Assume you have downloaded swf file from fusionchart website and kept in your "file resources)
Next add text field (Computed for Display) called "ChartSize" and will have following formula ,
"900" : "345"
Next add text field (Computed for Display) called "Colors" and will have following formula,
"99CCFF" : "FF99CC" : "CC9900" : "99CC99" : "9999FF" : "FFCC66" : "CCCC66" : "9999CC" : "FFCCCC" : "99FFCC" : "CCCCFF" : "99CC66"
Next add last text field called "ChartData", which will compute feeded data and build xml . here is the formula for same,
Important :
1) Make sure all the tags are closed properly.
2) Parent tag (graph) is started and ended properly.
3) Data type conversion. Numbers must be converted into text.
5- Add following code on your form and pass thru ,
here are the formula used on
That's it. Open your document ( which you have created earlier) on web , it will display nice Flash chart for you by month wise. here it is,
You can even create complex one using AJAX which will dynamically build xml string and pass it to swf file.I have done similar stuffs using LS and ajax. Here is the sample using LS,
You can download working copy from OpenNTF.org, Here is the link,
http://www.openntf.org/Projects/pmt.nsf/ProjectLookup/Flash%20Charts%20for%20Domino%20web%20application
Today I got a requirement to put a check if person is not using Internet Explorer higher than 6 and Mozila Firefox higher than 2.5 , don't allow them to access the site since site is developed for IE ( version 6 or later) and Mozila (2.5 or later).
The first Easy stuff I did to test @BrowserInfo("Platform") and @BrowserInfo("Version")formulas in Explorer,Mozila and Safari. I saw strange stuffs, IE shows type "Explorer" and version 7 ( Which was right because I have version 7), but Mozila and Safari both shows type as "Mozila" and version 5, Whereas I am having Mozila 3 and Safari 3.2. Soon I realized this is not going to be a easy fix.
Next, I thought to check "The Navigator Object" which is having two property to detect browser type and version
appName - holds the name of the browser
appVersion - holds, among other things, the version of the browser
But as soon as tested found , wrong results again. Also found following warning in W3Schools ,
IMPORTANT! The version number is WRONG in IE 5.0 or later! Microsoft starts the appVersion string with the number 4.0. in IE 5.0 and IE 6.0!!! Why did they do that??? However, JavaScript is the same in IE6, IE5 and IE4, so for most scripts it is ok.
Now what Next.. After spending couple of hours able to implement JavaScript which works well for all the browsers and provides correct type with version number. Here was my final JS code,
You just need to use in the JS file or JSHeader and call their methods like,
Since I can't post JS directly on the blog so posted as image, write me for JS code.
This tip is published in Search Domino website , Vote this tip if you like...
Whenever I need any sort of help in designing web form or css or even need to bring something hybrid, I do follow following useful articles . Hope these will helpful to others too.
1- CSS-Based Forms: Modern Solutions
2- Top 10 CSS Table Designs
3- 10 Useful Techniques To Improve Your User Interface Designs
4- 170+ Expert Ideas From World’s Leading Developers
5- AJAX, DHTML and JavaScript Libraries
6- 80+ AJAX-Solutions For Professional Coding
7- Pagination Gallery: Examples And Good Practices
8- Data Grids with AJAX, DHTML and JavaScript
9- 53 CSS-Techniques You Couldn’t Live Without
10- 75 (Really) Useful JavaScript Techniques
Few months back I was working in SharePoint designer and noticed it provides plenty of tools and easy way to deal with your web page structure,JS, CSS and other DOM models . You can easily identify which styles are applied, which are overridden and even structure of your inline styles. I must say people with no experience on web can develop web pages using SharePoint designer :-) . On the other hand when we do web development in Lotus Notes ( prior to R8.5 release ), I must say most of the developers either write CSS/JS in some web editor (I prefer EditPlus) or copy from some cool website using URL manipulation. I do most of the time :). Recently I had found free web tool which is quite cool as more or less like SharePoint. It's called Firebug , which can be used as a add-ons with Mozilla.You can just download it and open any website in Mozilla and go to Tools->Firebug and Choose options.
What can you do with Firebug ?
1- You can inspect HTML of the page. Shown below ,
2- You can inspect CSS or even can steal CSS from any site without doing any URL manipulation :)
3- Inspect JS files
4- Find out which styles are overridden , DOM structure and even layout
It makes my web development really easy without distracting much towards Microsoft tool ;-). Just visit Firebug and see what more you can do with it.
Today I encountered something interesting, It was small but yet to gave me some challenge. In one of the web form we have Dojo text area. What we found while testing if user copy-paste some contents from MS word/excel contents get truncated or even impossible to read.Something like,
But if you just close and re-open the document , everything looks perfect. here it is,
Now what could be easy to implement solution without doing much changes from ground. What I thought lets create one button next to the existing "text Area" field say "click to paste". It will open a dialog box with another "text area" field which will allow to write or paste the contents from various sources.Once done you can click OK and dialog box's contents moved to the original text area which is in read only mode.It could be much simpler if you have just a text field or something to pass via Query String. After little mind-boggling I was able to fix this. Here are the logic.
Lets assume my original text area field name is "Body_1". So, Following code is implemented on "Click to Paste" button (which is mentioned on the top) ,
var childWin;
var pData
childWin=null;
if ( document.getElementById('Body_1').value != "" ) {
childWin=window.open('server/db/form?OpenForm','popup','status=0,toolbar=0,scrollbars=0,resizable=0,width=500,height=145,top=500,left=550')
}
else {
window.open('server/db/form?OpenForm','popup','status=0,toolbar=0,scrollbars=0,resizable=0,width=500,height=145,top=500,left=550')
}
Next, Lets assume our dialog box's field name is "Body". Here is the code which is written on "onLoad" event of the dialog box to retrieve parent's value ,
document.getElementById("Body").value = window.opener.document.getElementById("Body_1").value
At the end here is the code which will set Child form's field contents to parent ,
var pData= document.forms[0].Body.value
window.opener.document.getElementById('Body_1').value= pData
window.close();
window.opener.document.getElementById("btnPaste").value="Click to Edit"
Lets see all steps in image ,
Step 1- When form loads ,
Step 2 - Clicked on "Click to paste" to paste the contents ,
step 3 - Last step to edit the text again ,
Simple and easy to use , right :)
Few days back I had requirement to build dynamic DHTML menu based on the user's personal configuration document. Initially I thought to build everything in JS to avoid any mess up.But after getting the final specs I found , I need to build the menu based on the existing menu which is on flash.Funny thing was I don't have any knowledge about "Flash", moreover existing flash menu was horrible than my expectation.However it was quite good to see something new which I have never done. I had started looking the whole menu structure in and out and able to understand what actually they have done.Anyways, It's quite complex to explain flash menu stuffs in notes, probably will write separate blog for that. Come to the point , How @For had spoiled my few hours :-)
After getting the logic I had decided to build menu using HTML LIST tag and apply mouseover effect so that it gives button kinda effect when menu generates .In few hours I finished the menu part which was getting generated quite well on the image which was actually the company logo(theme).
Now my next step was to create LIST tag in loop, something like
LIST START
For (i =1 ; i <@length(menu_title) ; i++)
[]
LIST END
Since I was retrieving logged in user's configuration contents using @formula so I thought lets try formula to build the menu. I had created three fields , one to build menu contents (something like menu_title^menu_url) , second to keep only menu title and third to keep only menu url.See the snippet,
I was confident enough to wrap up in few minutes. Next I have designed the skeleton for my menu on the form and applied css and other logic to build the menu.Here was the final design,
I put following formula for Computed Value
Saved the form and boom... When I checked the output on web, found printed "1"..
I felt really strange what I have done wrong ..Checked the code so many times but didn't find anything wrong in the code. Thanks to "Kerr" (one of the member from Lotus Site) help me to find out what silly I have done in my code.. I just forgot or missed to save the tag information in temp variable.. It should be something like ,
You know what when I checked the help file it was mentioned in one of the example , but I just missed the point :(
Hope next time me or anyone who read this will not forget which I did :)
