logo

Effective use of the FileCloseWindow Command

When designing forms in domino we can easily use some of the same standard actions that we would use in the Notes Client i.e. EditDocument, FileSave, FileCloseWindow. Domino can then translate these in to actions that run via the web browser.

Most of these work perfectly, for example a submit button that contains both @Command([FileSave]) and @Command([FileCloseWindow]) or an "Edit" button with just @Command([EditDocument]). However, creating a Close button in forms and documents using just @Command([FileCloseWindow]) on its own can have undesirable effects.

The reason for this is that domino needs to know where to go after the close. In the Notes client this is not a problem as you don't need to go anywhere. Just show the window beneath it. The browser is different though as there is no window "beneath" it. For this reason domino has some rules for what to do after "closing" a window.

I've been doing a bit of testing (in R5) to see exactly what it is doing and am going to share it with you now.

If you're in a document with a URL similar to the one below, with either "?OpenDocument" or "?EditDocument" appended:

server/dir/db.nsf/view/document

the URL resulting from a FileCloseWindow will depend entirely on the view that is being used. If it is either the Name, Alias or UniqueID of the view then domino will open the following URL:

server/dir/db.nsf/ViewID?OpenView

Which is fine in most circumstances. If, however, you didn't know the view in which the document belongs when you created the URL and simply used a "0" in its place, like below:

server/dir/db.nsf/0/document

then domino does not know where to go afterward as there is no view called "0", even though the above URL is perfectly legal. The result would be to open the database at the root level. Not what most users would expect to happen.

Similarly, if you are in a new document ("?OpenForm") or your are in a view (via its template) then FileCloseWindow will also take you to the root database level:

server/dir.db.nsf?OpenDatabase

This all leads me to the conclusion that FileCloseWindow is not really of much use, on its own, and that it would be much more useful to use a more suitable function in its place. For example, you can have a button that says "Close" on it but actually all it does it use @Command([OpenView]) to return to a suitable view. You could also reopen the document in read-mode if a user hits close while editing an existing document or reopen a view if it is a new document by using the following simple formula:

URL := @If(@IsNewDoc; "view?OpenView"; @Text(@DocumentUniqueID) + "?OpenDocument");
@URLOpen(URL)


It is also worth pointing out that using FileCloseWindow in R5 is slightly different than in R4. This is due to the change in the _doClick function that domino uses to handle most calls to backend functions. The new R5 version calls the onSubmit event of the form before submitting it. If all you want to do is close the document and not do any of the validation you may have placed in the onSubmit event then this will cause you problems. Using @URLOpen gets around this as it doesn't need to submit the form, it just opens the new URL.


Feedback

  1. Use of cookie to open the good view

    Hello,

    Just to share with you a technic (maybe you know it) in order to open the view you just come from when you save a document on the Web.

    If you have expanded one category of a view to find and open document, and then save the document with a "[fileSave], [FileClose]", you will return to the view, but all the categories will be collapsed or expanded (depends of the properties of the view). So you have lost your document (if you have done 15 "Next page" to found if, you are also very angry! :-)

    What I do is that :

    In my form $$ViewTemplateDefault, I have on the onUnload event a JavaScript code who writes in a cookie the url of the current location (which is obviously the url of a view command).

    In all my forms, in the onLoad event, I have a JavaScript code who write the value of the cookie in a hidden field of the form.

    Finaly in the $$Return of my forms I have this code "[" + FieldWhoNowContainsValueOfCookie + "]".

    If the document is in read mode you can put a JavaScript code like this :

    location.href = functionThatGetCookieWhoContainsUrlOfTheViewYouComeFrom()

    in a "close" button.

    This is usefull when you can't use "history.back()" because the document contains sections or is refreshed/reloaded a number of time you can't estimated.

    This is not my computer so I can't do "copy paste" of my code, sorry.

    Congratulations for your scores at JavaScript exam !

    Mine was 92% (I am also CLPP dev).

    CodeStore.net is very cool !

    Bye,

    Fabrice

    1. Re: Use of cookie to open the good view

      Alternatively rather than use a cookie if you create a hidden field called "HTTP_Referer" this contains the url of the page used to reach the current page and the value can be used either in an @URLOPEN command, a $$Return field or in a simple javascript button formula e.g.

      Location.href = document.forms[0].HTTP_Referer.value

      This works no matter where the user has come from

      Thanks for the site it has been a great help to me in getting started with JavaScript and Notes.

    2. Re: Use of cookie to open the good view

      Hello,

      Because recently I received a mail asking to me details about the technic of cookie, I complete my previous message :

      A/ ------------------------------

      In the $$ViewTemplateDefault, put this code in the UnLoad event :

      doCookie("ViewReferer", location.href);

      In the JS Header, copy this code :

      function doCookie(cookieName, value) { if(document.cookie) { index = document.cookie.indexOf(cookieName); } else { index = -1; } if (index == -1) document.cookie = cookieName+"=" + value + ";expires=Tuesday, 01-Apr-2020 08:00:00 GMT"; else { countbegin = (document.cookie.indexOf("=", index) + 1); countend = document.cookie.indexOf(";", index); if (countend == -1) { countend = document.cookie.length; } document.cookie=cookieName+"="+value+";expires=Tuesday, 01-Apr-2020 08:00:00 GMT"; } }

      B/ ------------------------------

      B 1. In the form used to access documents, put a field named HTTP_COOKIE, computed for display.

      B 2. Just below, put another field named ViewReferer (for example), computed for display, with this code :

      tmp := @Right ( HTTP_Cookie ; "ViewReferer=") ; tmp2 := @If ( @Contains(tmp ; ";") ; @Left( tmp ; ";") ; tmp ) ;

      @If ( tmp2 = "" ; tmp ; tmp2 )

      B 3. Put a field named DefaultView (for example), computed for display, and enter the name of the default view of your web application.

      For example : "TopicsByDate" in the case of a forum.

      B 4. Put a button or a Hospot named for example "Back to view", and enter this formula :

      @SetTargetFrame("_self");

      url := @If( ViewReferer != "" ; ViewReferer ; @Subset(@ViewTitle ; -1) != "" ; DbNameWeb + "/" + @Subset(@ViewTitle ; -1) + "?OpenView" ; DbNameWeb + "/" + DefaultView + "?OpenView" ) ;

      @URLOpen(url)

      What this code means ?

      When the user will click on the button : 1. User comes from a view, and his browser can manage cookie => go to the view at the "good" position (url is in the cookie) 2. User comes from a view, and his browser cannot manage cookie and the document is in edit mode => go to the "begin" of the view (with @viewtitle) 3. Browser cannot manage cookue and the document is in read mode => go to the begin of the default view (with the view indicated in the field DefaultView).

      That's it !

      You can also put a formula like this in the $$Return : "[" + ViewReferer + "]" ; so when user submit a document he get back directly to the view at the good position.

      My english is quite bad, but I hope now everybody will get the trick...

      Kindest regards,

      Fabrice P (France)

      Show the rest of this thread

  2. "Smart" cancel for when editing a document

    Not sure if this is related to your quandry about using the "FileCloseWindow" command for the Web but I have found very useful information in your site so I hope to give a little back.... :-)

    I provide an action button to logically "close" the document when opened in a Web browser that is based on whether the document is in Read or Edit mode.

    When in (Web) Read mode there is a "Go Back" action:

    // Shared Action: Go Back // Hide: Notes, Edit // Note: Use only for forms - for Web interface // Note: Use Cancel for Edit mode

    history.back()

    =====

    When in (Web) Edit mode there are two buttons, one to "Save & Close" and one to "Cancel":

    // Shared Action: Save & Close // Hide: Notes, Read // Note: Use only for forms - for Web interface

    // Only submit the document if all the fields validated correctly if (validateFormFields()) { thisform.submit(); }

    =====

    // Shared Action: Cancel // Hide: Notes, Read // Note: Use only for forms - for Web interface // Note: Use Go Back for Read mode

    // When a Domino Web page is reloaded, such as by a refresh fields or by selecting a tab on a // tabbed table, the page is reloaded with the same URL, but now with "&Seq=n" appended, // where "n" is the value indicating the number of times the page has been reloaded. // We want to return to the page that was loaded before the current page, no matter how many // times the current page has been reloaded.

    var strCurURL = document.location.href; var index = -1; var nSeqNum = 0; var nSeqPos = strCurURL.indexOf("&Seq=");

    if ( nSeqPos != -1 ) { nSeqNum = strCurURL.substring(nSeqPos + 5, nSeqPos + 8); var nEndPos = nSeqNum.indexOf("#"); if (nEndPos != -1) { nSeqNum = nSeqNum.substring(0, nEndPos); } nEndPos = nSeqNum.indexOf("&"); if (nEndPos != -1) { nSeqNum = nSeqNum.substring(0, nEndPos); } index = index - nSeqNum; } // Ensure there are enough history pages to go back to if ( 0 - history.length > index) { history.back(); // Not enough history, so just go back 1 page } else { history.go(index); }

    =====

    Notes:

    There is no code in the "onSubmit" event for the form.

    There is a "validateFormFields" JS function defined in the "JS Header" for the form. This function does all the field validation and returns either false or true.

    There are also "Close", "Save & Close", and "Cancel" action buttons on the form for when the document is displayed in a Notes client.

    =====

    REM "Shared Action: Close"; REM " Hide: Web, Preview, Edit"; REM " Note: Only shown in Action button bar"; REM " Note: Use Cancel for Edit mode";

    @Command([FileCloseWindow])

    =====

    REM "Shared Action: Save & Close"; REM " Hide: Web, Read"; REM " Note: Use only for forms - for Notes interface";

    REM " Note: Cannot use @IsValid on the Web";

    REM "Only save the document if all the fields validated correctly"; @If(@IsValid; @Do(@Command([FileSave]); @Command([FileCloseWindow])); "")

    =====

    REM "Shared Action: Cancel"; REM " Hide: Web, Read"; REM " Note: Use only for forms - for Notes interface"; REM " Note: Use Close for Read mode";

    FIELD SaveOptions := 0; @Command([FileCloseWindow])

    1. Re: "Smart" cancel for when editing a document

      Cindy -

      Thanks for your idea of using the Seq=# to count the self.history number.

      Here is a REALLY easy to implement version. It just has to be a Link Hotspot in designer.

      Put the following formula in the Link Hotspot and it works great.

      y := @If ( @Contains (Path_Info; "Seq=") ; @Right(Path_Info; "Seq=") ; "0" ); x := @TextToNumber( y ) ; z := @Text( x+1 ) ; "javascript:self.history.go(-" + z + ")"

      Thanks for this site. It's been a real God-Send. Jeff

      Hide the rest of this thread

      1. Re: "Smart" cancel for when editing a document

        Nice simple solution using the Notes formula language....but I see a few potential problems.

        Take the following Domino URL for example:

        http://pppp/ffff.nsf/eeee?OpenForm&NewSeq=No&SEQ=3#4.

        Your code will pick up "No&SEQ=3#4." as the sequence number value. The actual value is "3".

        1. You should explicitly check for "&Seq=" by including the "&". You may pick up the wrong parameter, such as "&NewSeq=No", if you just check for "Seq=". Remember the Domino developer can add parameters to the URL for passing information between pages.

        2. Your code is missing a check for information added after the "&SEQ=" parameter in the URL.

        The code must check for a "&" or a "#" after the "&SEQ=" parameter to be sure only the sequence number value is parsed out of the URL.

        For example, Domino will add "#4." when you are using tabbed tables for the form, where "4." is the currently displayed table tab name.

        Note: In my code example, "4." was an internal name assigned by Domino. I did not explicitly name my table tabs in HTML in this particular example.

        1. Re: "Smart" cancel for when editing a document

          Hi Cindy,

          You're right! That's lazy coding on my behalf. Feel free to slap my wrist and send me to bed early.

          What I should have done is use a much more generic system that caters for *all* eventualities.

          Here's [<a href="unid/DOMM-4QABB3">an example</a>]...

          Thank you, Jake -codestore

Your Comments

Name:
E-mail:
(optional)
Website:
(optional)
Comment:



Navigate other articles in the category "Forms"

« Previous Article Next Article »
Create a 'Delete Document' link   Using Query_String parameters

About This Article

Author: Jake Howlett
Category: Forms
Keywords: View; Close; Submit; URL;

Options

Feedback
Print Friendly

Let's Get Social


About This Website

CodeStore is all about web development. Concentrating on Lotus Domino, ASP.NET, Flex, SharePoint and all things internet.

Your host is Jake Howlett who runs his own web development company called Rockall Design and is always on the lookout for new and interesting work to do.

You can find me on Twitter and on Linked In.

Read more about this site »