Some existing references, which using header protection through sections and edit restrictions
https://answers.microsoft.com/en-us/msoffice/forum/msoffice_word-mso_windows8/im-trying-to-lock-the-header-and-footer-on-a-word/1c0d34b3-bdb1-4a93-9969-181c8e198785
https://wordribbon.tips.net/T011567_Protecting_Headers_and_Footers.html
Different approach for locking data for editing since Word 2010
The simplier and more flexible way to restrict editing of headers, footers in Microsoft Word document is to use Richtext Content Control (https://msdn.microsoft.com/en-us/library/bb157891.aspx). To lock the header or footer (any other blocks could be used) from editing, deleting you could select content required to be locked and click on RichText content control in Developer ribbon. As a result your selection will be enclosed in RichText content control and you will be able to set properties whose disables editing and deleting of selected content.
Thursday, 23 March 2017
Tuesday, 13 September 2016
Lotusscript and Computed for Display fields
Problem description:
Have a computed for display field in notes form. Add button to form with lotusscript code like:
1) get value with getItemValue - you have value from computed for display
2) refresh ui document
3) get value with getItemValue - you have no value from computed for display field
4) repeat operation with the same result
Resolution:
Put @Getfield("AnyField") formula in PostRecalc event
1) get value with getItemValue - you have value from computed for display
2) refresh ui document
3) get value with getItemValue - you have the actual value (if changes) from computed for display
Have a computed for display field in notes form. Add button to form with lotusscript code like:
1) get value with getItemValue - you have value from computed for display
2) refresh ui document
3) get value with getItemValue - you have no value from computed for display field
4) repeat operation with the same result
Resolution:
Put @Getfield("AnyField") formula in PostRecalc event
1) get value with getItemValue - you have value from computed for display
2) refresh ui document
3) get value with getItemValue - you have the actual value (if changes) from computed for display
Labels:
computed for display,
lotus notes,
lotusscript,
refresh
Friday, 4 December 2015
About Domino Designer Workpace restore
Source: http://www.intec.co.uk/restoring-domino-designer-including-working-sets/
Another one: http://www.lotusguru.com/lotusguru/LGBlog.nsf/d6plinks/20100310-83ESQC
Quote:
Since 8.5.0 I’ve been searching for everything that needs to be done to restore Domino Designer. Some time ago I blogged about exporting and importing Domino Designer preferences but I had always struggled to work out which files / folders were required for Working Sets.
Today I decided to do a clean install and finally managed to track down all the relevant folders to have working sets installed in a few seconds. All are in the workspace folder
- workspace stores all the relevant folders for servers and applications you’ve accessed
- workspace.metadata.plugins/org.eclipse.ui.workbench has settings for various dialogs, plus the critical file workingsets.xml. This looks like it has the configuration for the working sets themselves and points to paths of relevant files. I copied the whole folder.
- workspace.metadata.plugins/org.eclipse.core.resources has the projects referenced in the workingsets.xml. The whole folder is required. The .location files in each project point to the location using a URI relative to JNSF, which I suspect is the workspace folder
- workspace.metadata.plugins/com.ibm.designer.domino.ide.resources has a file that maps the projects to the actual servers
Copy those into a clean install, and you have “working” working sets in a few seconds.
I then chose to manually install all the additional plugins, but those appear to be in workspace.configorg.eclipse.update. To get the list of locations I had previously used in Domino Designer, I just copied a backup of bookmark.xml into that folder.
Monday, 29 June 2015
Domino Client Certificate authentication (web services consumer/provider)
Short description of problem and requirements:
Required to provide SSL Client authentication for IBM/LOTUS Domino users and other remote systems.
Integrate web services without storing username/password for Web Service connections consumers/providers or providing anonymous access.
Problem resolution example:
1) In Domino server document for SSL authentication options must set Client Certificate to "Yes".
How domino recognizes connecting client with certificate. It searches address book for matching user/server with corresponding mapped certificate.
Web Service provider - uses standard authentication - user must send client certificate to server. If this type of authentication is enabled, then there should be no problem.
Web Service consumer - using IBM Notes consumer we should set SSL option for connection, that Client Certificate must be sent and for this purpose additional option must be set before connecting Setssloptions(NOTES_SSL_SEND_CLIENT_CERT).
Where are the benefits?
You can build SOA based applications and integrate Lotus Applications with Web Services, so it could be later exposed to other applications.
Possible scenario:
1) Create Web service, that approves some document.
It could be used by:
a) Notes client - create internet certificate for user and import in notes ID. Approved document from LN Client.
b) Same Domino server with Client certificate authentication enabled (no username/password required). Server side scripts.
c) Web browser client - if server uses username/password authentication - user already authorized for operation.
d) External applications - create new user in address book, create client certificate, integrate.
Required to provide SSL Client authentication for IBM/LOTUS Domino users and other remote systems.
Integrate web services without storing username/password for Web Service connections consumers/providers or providing anonymous access.
Problem resolution example:
1) In Domino server document for SSL authentication options must set Client Certificate to "Yes".
How domino recognizes connecting client with certificate. It searches address book for matching user/server with corresponding mapped certificate.
Web Service provider - uses standard authentication - user must send client certificate to server. If this type of authentication is enabled, then there should be no problem.
Web Service consumer - using IBM Notes consumer we should set SSL option for connection, that Client Certificate must be sent and for this purpose additional option must be set before connecting Setssloptions(NOTES_SSL_SEND_CLIENT_CERT).
Where are the benefits?
You can build SOA based applications and integrate Lotus Applications with Web Services, so it could be later exposed to other applications.
Possible scenario:
1) Create Web service, that approves some document.
It could be used by:
a) Notes client - create internet certificate for user and import in notes ID. Approved document from LN Client.
b) Same Domino server with Client certificate authentication enabled (no username/password required). Server side scripts.
c) Web browser client - if server uses username/password authentication - user already authorized for operation.
d) External applications - create new user in address book, create client certificate, integrate.
Monday, 15 December 2014
Copy/Paste from applications to Notes into text fields (international characters)
The problem (sample with cyrilic symbols):
I had a very interesting problem with copying data, which contained international characters, from Microsoft office applications to Lotus Notes. So if you copy/paste into RichText field, there is workaround, that it could be pasted as plain text, but when you try to paste into Notes style text field, there is no options to do that. Using Lotus Notes e-mail, I've noticed, that copy/pasting into Native OS Style fields works well. So the workaround for that type of problem is to create form with one Native OS style field and add PostOpen event, which pastes data into that field, than copies that data again and closes the form. As a result, clipboard will contain correct data, to paste into Notes style field
You can create simple hotspot near the required field, which opens form with one field and then pastes resulting data in target field.
I had a very interesting problem with copying data, which contained international characters, from Microsoft office applications to Lotus Notes. So if you copy/paste into RichText field, there is workaround, that it could be pasted as plain text, but when you try to paste into Notes style text field, there is no options to do that. Using Lotus Notes e-mail, I've noticed, that copy/pasting into Native OS Style fields works well. So the workaround for that type of problem is to create form with one Native OS style field and add PostOpen event, which pastes data into that field, than copies that data again and closes the form. As a result, clipboard will contain correct data, to paste into Notes style field
You can create simple hotspot near the required field, which opens form with one field and then pastes resulting data in target field.
Tuesday, 22 July 2014
Lotus Outline BUG
Found interesting bug in Lotus Notes, when outline is embedded in form and in some cases disappears from UI.
Simple experiment to reproduce the problem.
1) Create form
2) Create outline
3) Add button to form with code like @SetField("SomeField";"12345") or call ws.currentdocument.document.replaceitemvalue ("SomeField","1111")
4) Add outline to form
5) Save form.
Close Lotus Notes and delete cache.ndk from data directory.
Run Lotus Notes. Open created form in Lotus Notes client. Push the button - voila! Outline disappears!
Next time You open same form and push the button - it works fine (outline is in place).
The main problem is that, this only happens with non-cached outlines in cache.ndk. If You have 2 replicas on multiple servers, then opening each replica and pushing then button reproduces the problem again and again (possible recache for each replica?).
Workaround for this issue is, that You could use some form with all outlines included and loaded before main form - "cache" init form - it should load first, then the working form.
P.S. notes 7.0.3 has this bug I haven't found any workaround for it, but in 7.0.4 and 8+ works fine with cache form.
Simple experiment to reproduce the problem.
1) Create form
2) Create outline
3) Add button to form with code like @SetField("SomeField";"12345") or call ws.currentdocument.document.replaceitemvalue ("SomeField","1111")
4) Add outline to form
5) Save form.
Close Lotus Notes and delete cache.ndk from data directory.
Run Lotus Notes. Open created form in Lotus Notes client. Push the button - voila! Outline disappears!
Next time You open same form and push the button - it works fine (outline is in place).
The main problem is that, this only happens with non-cached outlines in cache.ndk. If You have 2 replicas on multiple servers, then opening each replica and pushing then button reproduces the problem again and again (possible recache for each replica?).
Workaround for this issue is, that You could use some form with all outlines included and loaded before main form - "cache" init form - it should load first, then the working form.
P.S. notes 7.0.3 has this bug I haven't found any workaround for it, but in 7.0.4 and 8+ works fine with cache form.
Friday, 2 November 2012
Lotus Notes. Getting user HOME on MACINTOSH
I had run in problem building application for MACINTOSH in LN. It was required to install some user files for regular use and it should be installed in user home directory. So then problem was, that Lotusscript does not gives user home directory location using Environ, or NotesSession.getEnvironmentString.
First my attempt were to execute shell like "env > /tmp/userenv.txt" and then read the file, parse and get HOME directory from file - I don't like this, because You need to create a file on disk.
Second attempt were to search for dll containing standard C function getenv, which must return environment variable by specified name. So the library found is "libSystem.dylib" and resulting declaration in LS library, agent {Declare Function mac_getenv Lib "libSystem.dylib" Alias "getenv" (ByVal varnameAs String) As String}, so call mac_getenv("HOME") and voila!
First my attempt were to execute shell like "env > /tmp/userenv.txt" and then read the file, parse and get HOME directory from file - I don't like this, because You need to create a file on disk.
Second attempt were to search for dll containing standard C function getenv, which must return environment variable by specified name. So the library found is "libSystem.dylib" and resulting declaration in LS library, agent {Declare Function mac_getenv Lib "libSystem.dylib" Alias "getenv" (ByVal varnameAs String) As String}, so call mac_getenv("HOME") and voila!
Creating Type-ahead searches in Lotus Notes
This will be short article about how to build user friendly type-ahead searches for Lotus Notes clients.
This will not be tutorial, but only idea and some basic concepts.
Basic instruments:
1) Form - dialog basic form
2) Dialog list field - search text entering
3) Query recalc - search performing
4) NotesTimer - for large database search optimization
5) Table with hotspots - user friendly result display
Example to-do:
This will not be tutorial, but only idea and some basic concepts.
Basic instruments:
1) Form - dialog basic form
2) Dialog list field - search text entering
3) Query recalc - search performing
4) NotesTimer - for large database search optimization
5) Table with hotspots - user friendly result display
Example to-do:
- Required to build dialog for searching data in database (people, organization, product or other object search).
- Build a dialog form, which will be called from our hotspot in some basic form (better to use dialog, because of complex design of search dialog)
- Add dialog list field, and put it in table, disable delimiters, add formula "" for choices, check refresh on each character.
- On query recalc add function to perform search before form is refreshed, get value from search field and compute formula and search for results. After search put result in fields, from whose will be computed out table. Maybe You will need to limit search starting from 2-3 characters entered in searchfield.
- Create table with row count about 10 result rows. You could build paged table or table with hotspot for more results in ex. ws.prompt LIST. Each row could consist of index, name of found entry, id, other info ex. No., Product Name, ID, Manufacturer. For table correctly to work it is required to add bunch of hide formulas and field formulas, for faster results, build one row with field indexes ex. No_1, Name_1, ID_1,Man_1, but results put in fields No,Name,ID,Man, so You can compute which entry to pick from result field for row ex. @getfield(@left(@thisname;"_"))[@tonumber(@right(@thisname;"_")] (add error handling :) ) - it's pretty easy to build row with this technique. For pickfield ex. Product Name add hotspot, to allow to pick clicking on entry directly and add script like call entrySelected(0). For faster 10 row run initially create fields with no index and then use copy/paste, because LN will add indexes - if You copy field Name, then paste result will be Name_1, next Paste, Name_2 (pretty easy).
- Next searched database contains a lot of records and each search if about 1,2 seconds, then it could be possible to add optimization with NotesTimer. Put code to create timer on queryrecalc and call search code on alarm, so if user types fast, then reset timer on refresh - do not perform search. If user stopped typing, then in about second Your search code will be executed (limitation of notestimer - no millisecond execution intervals) - search, put results, refresh.
Thank You for attention
Wednesday, 31 October 2012
One or more of the source document's attachment are missing
"One or more of the source document's attachment are missing" appearing for Design refresh or design copy.
Here is the way to try to fixup database without deletion of elements:
1) Create empty database
2) Set inherit design from corrupted database
3) Perform design refresh
4) On error check status bar for last design element displayed
5) Goto corrupted database and resave design element
In my sutiation main problem were with agents. So resaving them solved then problem.
Here is the way to try to fixup database without deletion of elements:
1) Create empty database
2) Set inherit design from corrupted database
3) Perform design refresh
4) On error check status bar for last design element displayed
5) Goto corrupted database and resave design element
In my sutiation main problem were with agents. So resaving them solved then problem.
Thursday, 30 June 2011
WEBDAV in XPAGES
What is WebDav, you can read at http://www.webdav.org.
WebDav and Lotus Domino
Basicaly webdav natively is supported only for managing file resources in .nsf databases. Read this for details: http://www.codestore.net/store.nsf/unid/FISR-6U8SN7
Next question is how to create webdav service for working with documents or set's of documents. This is very important when you're building DMS (document management systems). So why so late to create webdav in only 8.5 for document management?
Main problem,that there were no methods to pass back/receive binary data to browser, so webdav could be created only for txt type documents. Now binary data could be passed back using servlet response streams and read using request streams. Check the article about binary response in xpages.
Now our goal is to make available document listing and attachments for reading through webdav from simple database. db url is http://server/folder/db.nsf
Our webdav service will be served at xpage webdav.xsp. So full service url is http://server/folder/db.nsf/webdav.nsf
Now we have to create enable webdav on the server (native webdav support configuration), create website substitutions for better links (read this: http://www.dominoguru.com/pages/domino_rest_xpages_part1.html) for example when we entering url http://server/folder/db.nsf/webdav/documentid/attachmentname we get attachment, http://server/folder/db.nsf/webdav/documentid - attachment list for document. So basic substitution could be /folder/db.nsf/webdav/* -> /folder/db.nsf/webdav.xsp
Now we have create webdav.xsp, which will contain main service code. I will show only simple example, but it will be enough to start thinking in that way and build Your more complex application.
All service code could be put in beforeRenderResponse:
xpage main settings:
1. gzip compression for xpages disabled!
2. create form =false
3. rendered = false
Init code
var req:javax.servlet.http.HttpServletRequest=facesContext.getExternalContext().getRequest();
var resp:javax.servlet.http.HttpServletResponse=facesContext.getExternalContext().getResponse();
@code end we should end with
facesContext.responseComplete(); //because domino will generate html if we don' t do that
Next we should create blocks for handling requests, which contains of if's on request method. Ex. if (req.getMethod()=="OPTIONS"){} and so on
Each operation must return correct status code using resp.setStatus()
Main methods used for basic webdav support are:
1. "OPTIONS" - resource options, not required, should send (status: 200)
2. "PROPFIND" - property listing/dav folder contents with status (207)
3. "GET" - for resource downloading
now the theory of request urls and substitution. when user requests url like http://server/folder/db.nsf/webdav/documentid server will redirect it to http://server/folder/db.nsf/webdav.xsp and original requested url will be available through req.getRequestURI(), which sould be parsed, to determine what to do with request and what kind of response should be formed. For example if we got request with url like: http://server/folder/db.nsf/webdav/documentid - we could return attachment list in document(PROPFIND method), when user browses folder and clicks on document/attachment GET request is initated with HREF specified in returning XML by PROPFIND method handler. So on get request we are returning attachment data.
Look for sample code:
In sample code on propfind returned attachment list in document, which found by unid.
In get request attachment data is returned.
var req:javax.servlet.http.HttpServletRequest=facesContext.getExternalContext().getRequest();
var resp:javax.servlet.http.HttpServletResponse=facesContext.getExternalContext().getResponse();
var result="";
if (req.getMethod()=="OPTIONS"){
resp.setStatus(200);
resp.setHeader("DAV","1, 2")
resp.setHeader("MS-Author-Via", "DAV")
resp.setHeader("Allow","OPTIONS, GET, HEAD, POST, DELETE, TRACE, PROPPATCH, COPY, MOVE, LOCK, UNLOCK, PROPFIND")
resp.setContentType("application/xml")
resp.setContentLength(0);
}else if (req.getMethod()=="PROPFIND")// req.getMethod()=="GET")
{
resp.setStatus(207);
resp.setHeader("DAV","1, 2")
resp.setHeader("MS-Author-Via", "DAV")
resp.setHeader("Allow","OPTIONS, GET, HEAD, POST, DELETE, TRACE, PROPPATCH, COPY, MOVE, LOCK, UNLOCK, PROPFIND")
resp.setContentType("application/xml; charset=utf-8")
var writer=resp.getWriter();
result+=""
result+=""
result+=" "+req.getRequestURI()+"/folder/ folder HTTP/1.1 200 OK "
try{
var doc:NotesDocument=database.getDocumentByUNID("DBFDB0C60BF0B073C22578BE00406E45")
attachs=session.evaluate("@AttachmentNames",doc)
for (i=0;i "+req.getRequestURI()+"/"+attachs[i]+" "+attachs[i]+" application/octet-stream "+emb.getFileSize()+" HTTP/1.1 200 OK "
}
}catch(e){
}
result+=" "
writer.write(result);
writer.flush();
resp.setContentLength(result.length);
facesContext.responseComplete()
}else if (req.getMethod()=="GET"){
resp.setStatus(200);
var writer=resp.getOutputStream()
resp.setHeader("DAV","1, 2")
resp.setHeader("MS-Author-Via", "DAV")
resp.setHeader("Allow","OPTIONS, GET, HEAD, POST, DELETE, TRACE, PROPPATCH, COPY, MOVE, LOCK, UNLOCK, PROPFIND")
resp.setContentType("application/msword")
resp.setHeader("Content-Disposition","attachment; filename=testdocument")
var doc:NotesDocument=database.getDocumentByUNID("DBFDB0C60BF0B073C22578BE00406E45")
var attach:NotesEmbeddedObject=doc.getAttachment("testdocument")
if (attach!=null)
{
var fin:java.io.InputStream = attach.getInputStream()
var flength=fin.available();
while (fin.available()>0)
{
writer.write(fin.read());
}
writer.flush();
}
resp.setContentLength(flength);
facesContext.responseComplete()
doc.recycle()
}
P.S. if You need some detailed info on this or some help, then just PM, i' ll write back and post additional comment on this. Sorry, but have no time to fully explain (described just main steps)
WebDav and Lotus Domino
Basicaly webdav natively is supported only for managing file resources in .nsf databases. Read this for details: http://www.codestore.net/store.nsf/unid/FISR-6U8SN7
Next question is how to create webdav service for working with documents or set's of documents. This is very important when you're building DMS (document management systems). So why so late to create webdav in only 8.5 for document management?
Main problem,that there were no methods to pass back/receive binary data to browser, so webdav could be created only for txt type documents. Now binary data could be passed back using servlet response streams and read using request streams. Check the article about binary response in xpages.
Now our goal is to make available document listing and attachments for reading through webdav from simple database. db url is http://server/folder/db.nsf
Our webdav service will be served at xpage webdav.xsp. So full service url is http://server/folder/db.nsf/webdav.nsf
Now we have to create enable webdav on the server (native webdav support configuration), create website substitutions for better links (read this: http://www.dominoguru.com/pages/domino_rest_xpages_part1.html) for example when we entering url http://server/folder/db.nsf/webdav/documentid/attachmentname we get attachment, http://server/folder/db.nsf/webdav/documentid - attachment list for document. So basic substitution could be /folder/db.nsf/webdav/* -> /folder/db.nsf/webdav.xsp
Now we have create webdav.xsp, which will contain main service code. I will show only simple example, but it will be enough to start thinking in that way and build Your more complex application.
All service code could be put in beforeRenderResponse:
xpage main settings:
1. gzip compression for xpages disabled!
2. create form =false
3. rendered = false
Init code
var req:javax.servlet.http.HttpServletRequest=facesContext.getExternalContext().getRequest();
var resp:javax.servlet.http.HttpServletResponse=facesContext.getExternalContext().getResponse();
@code end we should end with
facesContext.responseComplete(); //because domino will generate html if we don' t do that
Next we should create blocks for handling requests, which contains of if's on request method. Ex. if (req.getMethod()=="OPTIONS"){} and so on
Each operation must return correct status code using resp.setStatus()
Main methods used for basic webdav support are:
1. "OPTIONS" - resource options, not required, should send (status: 200)
2. "PROPFIND" - property listing/dav folder contents with status (207)
3. "GET" - for resource downloading
now the theory of request urls and substitution. when user requests url like http://server/folder/db.nsf/webdav/documentid server will redirect it to http://server/folder/db.nsf/webdav.xsp and original requested url will be available through req.getRequestURI(), which sould be parsed, to determine what to do with request and what kind of response should be formed. For example if we got request with url like: http://server/folder/db.nsf/webdav/documentid - we could return attachment list in document(PROPFIND method), when user browses folder and clicks on document/attachment GET request is initated with HREF specified in returning XML by PROPFIND method handler. So on get request we are returning attachment data.
Look for sample code:
In sample code on propfind returned attachment list in document, which found by unid.
In get request attachment data is returned.
var req:javax.servlet.http.HttpServletRequest=facesContext.getExternalContext().getRequest();
var resp:javax.servlet.http.HttpServletResponse=facesContext.getExternalContext().getResponse();
var result="";
if (req.getMethod()=="OPTIONS"){
resp.setStatus(200);
resp.setHeader("DAV","1, 2")
resp.setHeader("MS-Author-Via", "DAV")
resp.setHeader("Allow","OPTIONS, GET, HEAD, POST, DELETE, TRACE, PROPPATCH, COPY, MOVE, LOCK, UNLOCK, PROPFIND")
resp.setContentType("application/xml")
resp.setContentLength(0);
}else if (req.getMethod()=="PROPFIND")// req.getMethod()=="GET")
{
resp.setStatus(207);
resp.setHeader("DAV","1, 2")
resp.setHeader("MS-Author-Via", "DAV")
resp.setHeader("Allow","OPTIONS, GET, HEAD, POST, DELETE, TRACE, PROPPATCH, COPY, MOVE, LOCK, UNLOCK, PROPFIND")
resp.setContentType("application/xml; charset=utf-8")
var writer=resp.getWriter();
result+=""
result+="
result+="
try{
var doc:NotesDocument=database.getDocumentByUNID("DBFDB0C60BF0B073C22578BE00406E45")
attachs=session.evaluate("@AttachmentNames",doc)
for (i=0;i
}
}catch(e){
}
result+="
writer.write(result);
writer.flush();
resp.setContentLength(result.length);
facesContext.responseComplete()
}else if (req.getMethod()=="GET"){
resp.setStatus(200);
var writer=resp.getOutputStream()
resp.setHeader("DAV","1, 2")
resp.setHeader("MS-Author-Via", "DAV")
resp.setHeader("Allow","OPTIONS, GET, HEAD, POST, DELETE, TRACE, PROPPATCH, COPY, MOVE, LOCK, UNLOCK, PROPFIND")
resp.setContentType("application/msword")
resp.setHeader("Content-Disposition","attachment; filename=testdocument")
var doc:NotesDocument=database.getDocumentByUNID("DBFDB0C60BF0B073C22578BE00406E45")
var attach:NotesEmbeddedObject=doc.getAttachment("testdocument")
if (attach!=null)
{
var fin:java.io.InputStream = attach.getInputStream()
var flength=fin.available();
while (fin.available()>0)
{
writer.write(fin.read());
}
writer.flush();
}
resp.setContentLength(flength);
facesContext.responseComplete()
doc.recycle()
}
P.S. if You need some detailed info on this or some help, then just PM, i' ll write back and post additional comment on this. Sorry, but have no time to fully explain (described just main steps)
Monday, 27 September 2010
Using XPAGES to pass back binary data
So I would like to write a little article about passing custom generated responses using XPAGES and how to use the for binary output.
Main problem in Lotus Domino editions till 8.5 is that we could not pass back binary data directly to WEB browser (using agent print/printing in form and so on). The only ways were, to create document, attach file, redirect attachment link or create file in shared web dir and pass direct link to user.
Now, when XPAGES with JSF technology comes to place it is possible to do so. Let's get it "how?".
At first You need to create and xpage element and set it render property to false - so nothing to be rendered.
Then You should choose xpage event, where to write the right code, which will serve data. So xpage has following events "beforePageLoad","afterPageLoad","beforeRenderResponse","afterRenderResponse","afterRestoreView". Most interesting for our example are "beforeRenderResponse","afterRenderResponse".
Classes to work with:
1. javax.faces.context.ExternalContext - needed to get response object
2. com.ibm.xsp.webapp.XspHttpServletResponse - needed to get outputstream
3. javax.servlet.ServletOutputStream - stream, where we will write data
XPAGE options to be set:
CreateForm = false
rendered = false
//CODE BLOCK START FOR this example it should be put in beforeRenderResponse
//Initialization
var extContext:javax.faces.context.ExternalContext = facesContext.getexgetExternalContext();
var response:com.ibm.xsp.webapp.XspHttpServletResponse = exCon.getResponse();
var writer:javax.servlet.ServletOutputStream = response.getOutputStream();
//setting response headers for browser to recognize data
response.setContentType("image/gif"); // content type of data, for other binary see mime types or put "application/octet-stream"
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Content-Disposition" ,"attachment; filename=image.gif"); //required if You need to pass it back as file
//convert sample hex to character codes.
var decoded=imgHex.split(" ");
var result=new Array();
for (var i=0;i<decoded.length;i++)
{
result[i]=(parseInt(decoded[i],16))
}
// result is an array containing character codes (byte array). How to prepare for other situations an array You should decide at Your own.
writer.write(result); // just write prepared array to output
//when all output is done. just tell that You have completed the response and close stream
facesContext.responseComplete();
writer.close();
//Sample data
//domino image in hex should move to initialization section
imgHex= "47 49 46 38 39 61 15 00 15 00 e6 00 00 00 00 00 ff ff ff ce 64 66 c9 65 67 e2 7b 7c ff 98 99 ce 65 69 a4 9f a3 68 66 69 a0 b5 ca c8 cc cd c9 cb ca 65 65 63 67 67 65 e5 e5 e2 ca ca c8 c7 c7 c5 f0 f0 ef eb eb ea a8 a8 a7 fe f3 8a fe f2 8c ff f2 8c fe f1 8b d6 d4 d0 ec eb e9 ea e9 e7 c8 c7 c5 f3 ac 38 f2 ad 38 f2 ac 3a f2 ac 3d fc be 59 fc be 5b f9 be 5a d0 cd c8 f4 ab 3a fc bc 5b fc bd 5c fb bc 5d e8 e6 e3 de dc d9 d7 d4 d0 d0 cd c9 d1 cd c8 c0 be bc ee ed ec 81 5b 48 84 59 46 82 5b 4a b7 83 6d b6 82 6d 83 59 49 84 5a 4a b8 81 6d 87 59 4a 84 5a 4c b8 7f 6c ba 7f 6d cd 65 64 cd 67 65 ca 66 66 ff 9a 98 ff 9b 99 fc fc fc ca ca ca ad ad ad ac ac ac 88 88 88 67 67 67 66 66 66 ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 21 f9 04 01 00 00 47 00 2c 00 00 00 00 15 00 15 00 00 07 9e 80 47 82 83 84 85 86 87 88 89 8a 8b 8c 06 03 8c 86 3d 3e 3f 3c 86 42 97 98 99 39 45 05 04 3b 0a 85 42 40 a3 a4 a3 36 14 43 46 02 0f 96 40 11 af b0 3a 14 20 24 30 46 0b ad b0 af 32 14 27 1d 31 07 46 41 ad 19 13 44 12 33 17 25 1c 37 13 18 c2 ad 0e 10 1b 3a 16 26 1f 38 13 0b 40 d0 a1 40 2e 13 33 15 22 1c 2f da 29 dc c3 de 1a 2d 08 21 1e 34 13 2a 18 18 e9 c4 28 0d 0c 35 13 09 2c 2b 23 f6 bc 95 1a 38 aa 1b 21 23 08 13 2a 54 a8 ae 50 90 87 10 23 46 84 44 b1 a2 c5 8b 8c 02 01 00 3b"
REFERENCES, where You could check how to output STRING data.
http://www.wissel.net/blog/d6plinks/SHWL-7MGFBN
http://www-10.lotus.com/ldd/nd85forum.nsf/7756aedc25e6d81285256324005ac76c/1e87cc63dfcf9412852575ae0005079f?OpenDocument - getResponseStream problem.
Main problem in Lotus Domino editions till 8.5 is that we could not pass back binary data directly to WEB browser (using agent print/printing in form and so on). The only ways were, to create document, attach file, redirect attachment link or create file in shared web dir and pass direct link to user.
Now, when XPAGES with JSF technology comes to place it is possible to do so. Let's get it "how?".
At first You need to create and xpage element and set it render property to false - so nothing to be rendered.
Then You should choose xpage event, where to write the right code, which will serve data. So xpage has following events "beforePageLoad","afterPageLoad","beforeRenderResponse","afterRenderResponse","afterRestoreView". Most interesting for our example are "beforeRenderResponse","afterRenderResponse".
Classes to work with:
1. javax.faces.context.ExternalContext - needed to get response object
2. com.ibm.xsp.webapp.XspHttpServletResponse - needed to get outputstream
3. javax.servlet.ServletOutputStream - stream, where we will write data
XPAGE options to be set:
CreateForm = false
rendered = false
//CODE BLOCK START FOR this example it should be put in beforeRenderResponse
//Initialization
var extContext:javax.faces.context.ExternalContext = facesContext.getexgetExternalContext();
var response:com.ibm.xsp.webapp.XspHttpServletResponse = exCon.getResponse();
var writer:javax.servlet.ServletOutputStream = response.getOutputStream();
//setting response headers for browser to recognize data
response.setContentType("image/gif"); // content type of data, for other binary see mime types or put "application/octet-stream"
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Content-Disposition" ,"attachment; filename=image.gif"); //required if You need to pass it back as file
//convert sample hex to character codes.
var decoded=imgHex.split(" ");
var result=new Array();
for (var i=0;i<decoded.length;i++)
{
result[i]=(parseInt(decoded[i],16))
}
// result is an array containing character codes (byte array). How to prepare for other situations an array You should decide at Your own.
writer.write(result); // just write prepared array to output
//when all output is done. just tell that You have completed the response and close stream
facesContext.responseComplete();
writer.close();
//Sample data
//domino image in hex should move to initialization section
imgHex= "47 49 46 38 39 61 15 00 15 00 e6 00 00 00 00 00 ff ff ff ce 64 66 c9 65 67 e2 7b 7c ff 98 99 ce 65 69 a4 9f a3 68 66 69 a0 b5 ca c8 cc cd c9 cb ca 65 65 63 67 67 65 e5 e5 e2 ca ca c8 c7 c7 c5 f0 f0 ef eb eb ea a8 a8 a7 fe f3 8a fe f2 8c ff f2 8c fe f1 8b d6 d4 d0 ec eb e9 ea e9 e7 c8 c7 c5 f3 ac 38 f2 ad 38 f2 ac 3a f2 ac 3d fc be 59 fc be 5b f9 be 5a d0 cd c8 f4 ab 3a fc bc 5b fc bd 5c fb bc 5d e8 e6 e3 de dc d9 d7 d4 d0 d0 cd c9 d1 cd c8 c0 be bc ee ed ec 81 5b 48 84 59 46 82 5b 4a b7 83 6d b6 82 6d 83 59 49 84 5a 4a b8 81 6d 87 59 4a 84 5a 4c b8 7f 6c ba 7f 6d cd 65 64 cd 67 65 ca 66 66 ff 9a 98 ff 9b 99 fc fc fc ca ca ca ad ad ad ac ac ac 88 88 88 67 67 67 66 66 66 ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 21 f9 04 01 00 00 47 00 2c 00 00 00 00 15 00 15 00 00 07 9e 80 47 82 83 84 85 86 87 88 89 8a 8b 8c 06 03 8c 86 3d 3e 3f 3c 86 42 97 98 99 39 45 05 04 3b 0a 85 42 40 a3 a4 a3 36 14 43 46 02 0f 96 40 11 af b0 3a 14 20 24 30 46 0b ad b0 af 32 14 27 1d 31 07 46 41 ad 19 13 44 12 33 17 25 1c 37 13 18 c2 ad 0e 10 1b 3a 16 26 1f 38 13 0b 40 d0 a1 40 2e 13 33 15 22 1c 2f da 29 dc c3 de 1a 2d 08 21 1e 34 13 2a 18 18 e9 c4 28 0d 0c 35 13 09 2c 2b 23 f6 bc 95 1a 38 aa 1b 21 23 08 13 2a 54 a8 ae 50 90 87 10 23 46 84 44 b1 a2 c5 8b 8c 02 01 00 3b"
REFERENCES, where You could check how to output STRING data.
http://www.wissel.net/blog/d6plinks/SHWL-7MGFBN
http://www-10.lotus.com/ldd/nd85forum.nsf/7756aedc25e6d81285256324005ac76c/1e87cc63dfcf9412852575ae0005079f?OpenDocument - getResponseStream problem.
Saturday, 10 April 2010
Embedded view from External DB
1. Standard method replacing replicaid in form using dxl.
2. Advanced method using forms, frameset and embedded editor.
You have 2 databases, form1 (db1) and view1 (db2) which should be displayed. How to make it without composite applications and DXL tools?
Simply:
1. Create frameset1 in db1 with 2 frames, Top and Bottom. Make top frame 1 Pixel height.
2. Create empty form in db1, let's call it Form1Embed, set it to open in frameset1 Top frame.
3. Create form or page in db2, let's call it Form2Embed. Add embedded view1 to this form. Then add simple code in postopen:
dim ws as new notesuiworkspace
dim uidoc as notesuidocument
set uidoc=ws.currentdocument
'// fill some field with universal id of uidoc.document, then set single category from this field for view1
What this code do? the uidoc we get is parent document (form1).
3. Embed Form1Embed in form1 through embedded editor.
4. In frameset1 Bottom frame compute db2 path and our created element Form2Embed (that Form2Embed could be opened)
Now what happeps when you open form1?
1. form1 is loaded
2. Embedded editor loaded for form1embed, lotus opens this form in frameset1 top frame, which is not visible. Then computes Bottom frame with our form2embed from db2, which on load gets form1 document and uses it unid as single category key.
2. Advanced method using forms, frameset and embedded editor.
You have 2 databases, form1 (db1) and view1 (db2) which should be displayed. How to make it without composite applications and DXL tools?
Simply:
1. Create frameset1 in db1 with 2 frames, Top and Bottom. Make top frame 1 Pixel height.
2. Create empty form in db1, let's call it Form1Embed, set it to open in frameset1 Top frame.
3. Create form or page in db2, let's call it Form2Embed. Add embedded view1 to this form. Then add simple code in postopen:
dim ws as new notesuiworkspace
dim uidoc as notesuidocument
set uidoc=ws.currentdocument
'// fill some field with universal id of uidoc.document, then set single category from this field for view1
What this code do? the uidoc we get is parent document (form1).
3. Embed Form1Embed in form1 through embedded editor.
4. In frameset1 Bottom frame compute db2 path and our created element Form2Embed (that Form2Embed could be opened)
Now what happeps when you open form1?
1. form1 is loaded
2. Embedded editor loaded for form1embed, lotus opens this form in frameset1 top frame, which is not visible. Then computes Bottom frame with our form2embed from db2, which on load gets form1 document and uses it unid as single category key.
Lotusscript External DB calls
Sometimes, it is required to call functions from other related databases and then we have to choose copy libraries or try to call using parameters, so that libraries stay where they belongs to.
At least we have 3 possible call methods to access script from other LN database.
1. Calling agent with parameterDocID, where we could pass 4 bytes of data (note id length FFFFFFFF). Traditionally noteid of profile document or other document to process is passed. For more flexibility, can be used bit masks if agent works with UI and has access to context.
Main problem for this method is restrictions to passing parameters and for agents contains large libraries each time agent is loaded, script libraries are loaded again and again and no cached.
2. Second method is calling dialogbox in external database, by creating document in that db. Then we can pass parameters with no document save, use lotus cache (form cached) and access external lotusscript. Main problem is to reopen document after processing if needed, so that code should be splitted in 2 dbs, call function will handle return data and that we normally could not hide that dialog if we need if we want to return data.
3. Third method is the trick (some type of mutation of second method) found is that each document or UI element where external functions could be called is enclosed in frameset with 1 pixel top frame. Then form should be setup to open in frameset second frame. Visually document opens as always and no UI difference visible. Top frame is used to call external function. How to call?
3.1 simple method. In external database create form, create postopen event on event start you can access context uidoc using notesuiworkspace.currentdocument. No params could be passed in this case. But this method uses cash, which creatly boosts performance. To call form use notesuiworkspace.composedocument in top frame.
3.2 advanced method. use the same technique as in 3.1, but no post open event, only cache source document, for later use. Then create on form at least 2 editable fields: 1 for initial focus, 2 for function call. in second field write code in entering event. How to pass parameters? in caller db script. like in 3.1, but now we need returning uidoc to pass parameters. Use like set uidoc=ws.composedocument. Now use uidoc.document to write parameters in opened doc, after finished, just use uidoc.GotoField(second field). This method is like calling extenal agents with more flexibility and cache.
At least we have 3 possible call methods to access script from other LN database.
1. Calling agent with parameterDocID, where we could pass 4 bytes of data (note id length FFFFFFFF). Traditionally noteid of profile document or other document to process is passed. For more flexibility, can be used bit masks if agent works with UI and has access to context.
Main problem for this method is restrictions to passing parameters and for agents contains large libraries each time agent is loaded, script libraries are loaded again and again and no cached.
2. Second method is calling dialogbox in external database, by creating document in that db. Then we can pass parameters with no document save, use lotus cache (form cached) and access external lotusscript. Main problem is to reopen document after processing if needed, so that code should be splitted in 2 dbs, call function will handle return data and that we normally could not hide that dialog if we need if we want to return data.
3. Third method is the trick (some type of mutation of second method) found is that each document or UI element where external functions could be called is enclosed in frameset with 1 pixel top frame. Then form should be setup to open in frameset second frame. Visually document opens as always and no UI difference visible. Top frame is used to call external function. How to call?
3.1 simple method. In external database create form, create postopen event on event start you can access context uidoc using notesuiworkspace.currentdocument. No params could be passed in this case. But this method uses cash, which creatly boosts performance. To call form use notesuiworkspace.composedocument in top frame.
3.2 advanced method. use the same technique as in 3.1, but no post open event, only cache source document, for later use. Then create on form at least 2 editable fields: 1 for initial focus, 2 for function call. in second field write code in entering event. How to pass parameters? in caller db script. like in 3.1, but now we need returning uidoc to pass parameters. Use like set uidoc=ws.composedocument. Now use uidoc.document to write parameters in opened doc, after finished, just use uidoc.GotoField(second field). This method is like calling extenal agents with more flexibility and cache.
Wednesday, 10 February 2010
Signing LN databases with Server ID with lotusscript
Sometimes for automation tasks developers need to perform design signing with server ID.
Lotus design updates consists of design refresh and aftersigning. Refresh could be automated by using Lotus C API (write request if you need info) and no Server signing functionality.
We have only some methods to do signing:
1. NotesDatabase.sign(), which works with only user ID and on UI
2. NotesDocument.sign() if we are getting design element by noteID or through NotesNoteCollection. It could be signed, but lastmodifed username will remain the same, so you will need to call signing agent twice 1. sign signing agent, 2. sign other database
3. Using admin requests database. This method is better if admin has normal access rights to perform such operations. You'll simply need to create admin request document for each database to be signed, then wait till things is done.
4. Sign using NotesAdministrationProcess class.
Here is sample code for request document. Check "admin4.nsf" on server, where to create request:
Dim sName As Variant
Dim uname As string
sName=Evaluate("@servername",reqDoc) 'db.server does not returns full server name
uname=s.Effectiveusername
With reqDoc
.Form="AdminRequest"
.FullName=uname
.ProxyAction="101" '// action for request - type of request. see admin4.nsf for more info in ProxyAction shared field
.ProxyAuthor=uname
.ProxyDatabasePath=signDB.FilePath
.ProxyNameList=signDB.Title
.ProxyOriginatingAuthor=s.effectiveusername
.ProxyOriginatingOrganization=nname.Organization
.ProxyOriginatingRequestUNID=reqDoc.universalid
.ProxyOriginatingTimeDate=Now
.ProxyProcess="Adminp"
.ProxyServer=sName(0)
.ProxyTextItem1="0"
.Type="AdminRequest"
Call .Replaceitemvalue("$OnBehalfOf", uname)
ForAll cItem In reqDoc.items
cItem.isSigned=True
End ForAll
Call .Sign()
Call .Save(True,True)
End With
Lotus design updates consists of design refresh and aftersigning. Refresh could be automated by using Lotus C API (write request if you need info) and no Server signing functionality.
We have only some methods to do signing:
1. NotesDatabase.sign(), which works with only user ID and on UI
2. NotesDocument.sign() if we are getting design element by noteID or through NotesNoteCollection. It could be signed, but lastmodifed username will remain the same, so you will need to call signing agent twice 1. sign signing agent, 2. sign other database
3. Using admin requests database. This method is better if admin has normal access rights to perform such operations. You'll simply need to create admin request document for each database to be signed, then wait till things is done.
4. Sign using NotesAdministrationProcess class.
Here is sample code for request document. Check "admin4.nsf" on server, where to create request:
Dim sName As Variant
Dim uname As string
sName=Evaluate("@servername",reqDoc) 'db.server does not returns full server name
uname=s.Effectiveusername
With reqDoc
.Form="AdminRequest"
.FullName=uname
.ProxyAction="101" '// action for request - type of request. see admin4.nsf for more info in ProxyAction shared field
.ProxyAuthor=uname
.ProxyDatabasePath=signDB.FilePath
.ProxyNameList=signDB.Title
.ProxyOriginatingAuthor=s.effectiveusername
.ProxyOriginatingOrganization=nname.Organization
.ProxyOriginatingRequestUNID=reqDoc.universalid
.ProxyOriginatingTimeDate=Now
.ProxyProcess="Adminp"
.ProxyServer=sName(0)
.ProxyTextItem1="0"
.Type="AdminRequest"
Call .Replaceitemvalue("$OnBehalfOf", uname)
ForAll cItem In reqDoc.items
cItem.isSigned=True
End ForAll
Call .Sign()
Call .Save(True,True)
End With
Thursday, 3 December 2009
XPAGES and Domino Web Services
Primary question how to call domino web services from XPAGES with authorization. There is method to do it:
1. Use Apache AXIS API to access and work with web services (API ref: http://ws.apache.org/axis/java/apiDocs/index.html).
2. Create service using
var service:org.apache.axis.client.Service = new org.apache.axis.client.Service();
3. Create call
var call:org.apache.axis.client.Call = service.createCall();
4. For authorization purposes if domino user is logged in:
call.setMaintainSession(true); - !Important
call.setProperty("Cookie","SessionID="+cookie.get("SessionID").getValue()+",DomAuthSessId="+cookie.get("DomAuthSessId").getValue())
5. Then simply call then web service and get your result:
var xmlType = new javax.xml.rpc.encoding.XMLType();
call.setTargetEndpointAddress({webServiceAddress});
call.setOperationName( {operationName} );
call.addParameter("INPUT1", xmlType.XSD_STRING, javax.xml.rpc.ParameterMode.IN);
call.addParameter("INPUT2", xmlType.XSD_STRING, javax.xml.rpc.ParameterMode.IN);
call.setReturnType(xmlType.XSD_STRING);
var a = new java.lang.Object[2];
a[0] = "param1";
a[1] = "param2";
var rating = call.invoke(a);
Authorization for SSO based login:
If your server is using basic http authorization, then previous demonstrated code should be modified to support basic http authorization. So we need to copy information from http header and pass it in web service request.
1. use headerValues global variable
2. check if headerValues.AUTHORIZATION or headerValues.containsKey("AUTHORIZATION")
3. set it in call property like call.setProperty("AUTHORIZATION",headerValues.AUTHORIZATION.nextElement()) or call.setProperty("AUTHORIZATION",headerValues.get("AUTHORIZATION").nextElement()).
Why is to use nextElement()? headerValues.get("AUTHORIZATION") returns single value enumeration, so to get string value we need to get element from list.
Problem detected when using apache axis in xpages internal requests (made using ssj - Server Side Javascript) is that sometimes domino server java class loader stop working correcly loading apache axis class org.apache.axis.client.Service() - required restart to work correctly.
1. Use Apache AXIS API to access and work with web services (API ref: http://ws.apache.org/axis/java/apiDocs/index.html).
2. Create service using
var service:org.apache.axis.client.Service = new org.apache.axis.client.Service();
3. Create call
var call:org.apache.axis.client.Call = service.createCall();
4. For authorization purposes if domino user is logged in:
call.setMaintainSession(true); - !Important
call.setProperty("Cookie","SessionID="+cookie.get("SessionID").getValue()+",DomAuthSessId="+cookie.get("DomAuthSessId").getValue())
5. Then simply call then web service and get your result:
var xmlType = new javax.xml.rpc.encoding.XMLType();
call.setTargetEndpointAddress({webServiceAddress});
call.setOperationName( {operationName} );
call.addParameter("INPUT1", xmlType.XSD_STRING, javax.xml.rpc.ParameterMode.IN);
call.addParameter("INPUT2", xmlType.XSD_STRING, javax.xml.rpc.ParameterMode.IN);
call.setReturnType(xmlType.XSD_STRING);
var a = new java.lang.Object[2];
a[0] = "param1";
a[1] = "param2";
var rating = call.invoke(a);
Authorization for SSO based login:
If your server is using basic http authorization, then previous demonstrated code should be modified to support basic http authorization. So we need to copy information from http header and pass it in web service request.
1. use headerValues global variable
2. check if headerValues.AUTHORIZATION or headerValues.containsKey("AUTHORIZATION")
3. set it in call property like call.setProperty("AUTHORIZATION",headerValues.AUTHORIZATION.nextElement()) or call.setProperty("AUTHORIZATION",headerValues.get("AUTHORIZATION").nextElement()).
Why is to use nextElement()? headerValues.get("AUTHORIZATION") returns single value enumeration, so to get string value we need to get element from list.
Problem detected when using apache axis in xpages internal requests (made using ssj - Server Side Javascript) is that sometimes domino server java class loader stop working correcly loading apache axis class org.apache.axis.client.Service() - required restart to work correctly.
Labels:
domino authorization,
web service,
xpages code reuse
Tuesday, 17 November 2009
Lotus Notes Outline tricks
Here are some tricks switching selected outline entry in embedded outlines:
1. We need for outline entries to define aliases, that could be used for referencing
2. For embedded outline should be defined name attribute (ex. "MyOutline").
3. To select required outline entry programmaticly it is required to set field "$MyOutline" ($ should be used as prefix for fields - full syntax "$"+OurDefinedOutlineName) value in opened document (to which embedded outline belongs) to outlineentry alias name (ex. "myDocs") and then doc should be refreshed, to apply entry selection.
P.S. @now there are problems to select outline entry just after form load, only using timer.
1. We need for outline entries to define aliases, that could be used for referencing
2. For embedded outline should be defined name attribute (ex. "MyOutline").
3. To select required outline entry programmaticly it is required to set field "$MyOutline" ($ should be used as prefix for fields - full syntax "$"+OurDefinedOutlineName) value in opened document (to which embedded outline belongs) to outlineentry alias name (ex. "myDocs") and then doc should be refreshed, to apply entry selection.
P.S. @now there are problems to select outline entry just after form load, only using timer.
Friday, 16 October 2009
How to add computed custom control to XPAGE at runtime
Very simple technique:
You need to know, that "include page" control could include not only page elements, but also custom control elements, but you should write then by Your hands.
So @1st create a repeater on page.
Then add include page control in repeater.
As repeater values set array of controls to add ex. ["ccontrol1.xsp", "ccontrol2.xsp",...]
use those values to compute page.
You need to know, that "include page" control could include not only page elements, but also custom control elements, but you should write then by Your hands.
So @1st create a repeater on page.
Then add include page control in repeater.
As repeater values set array of controls to add ex. ["ccontrol1.xsp", "ccontrol2.xsp",...]
use those values to compute page.
Subscribe to:
Posts (Atom)
