Wednesday, October 25, 2006

Leveraging PeopleSoft's JavaScript Save Warning

In a standard PeopleSoft session, a user will enter data into components. If a user forgets to save a component before navigating to a new component or opening a different transaction, then that user will loose all of the changes he or she made to the current transaction. To mitigate the potential for loosing changes, PeopleSoft displays a save warning message to remind the user to save. I am sure that you have encountered this message while working in PeopleSoft. I am also sure that you have noticed that PeopleSoft only displays this message if you change something within a component before navigating away from that component.

As you add custom JavaScript and HTML to your PeopleSoft implementation, you may find yourself in a situation where you need to know if a user has modified a component. For example, if you add an HTML Area to a component and that HTML Area contains links to related transactions, then, when a user navigates to a different transaction using these custom links, that user may loose any changes he or she made to the current transaction.

To warn a user before taking action using JavaScript, you can use the following PeopleSoft defined JavaScript functions:

  • saveWarning(frameName,form,target,url)
  • checkFrameChanged(objFrame)
  • checkAnyFrameChanged(startingFrame)
  • checkFormChanged(form, objFrame)

The saveWarning function will check for changes in a frame or form. If anything in the form or frame has changed, then the function will display a confirm message asking the user if he or she wants to save before leaving. Depending on the user's answer, the function will either navigate to the new url or cancel the action. If the user chooses to leave the component, then the function will return true.

saveWarning parameters:

  • frameName: the name of a frame to test
  • form: an object reference to a form to test
  • target: the target frame name for the url
  • url: the URL to load into the target frame

If you want to display a warning message for changes in any frame or form then you can substitute '' for the frame name and null for the form object. For example, the statement saveWarning('',null,'_self','') will cause the function to display a warning message if anything has changed in any frame or form.

If you just want to test for changes, and don't want to display a message, then you can use one of the check*Changed() functions. For example, to check for changes on any frame or any form, then you can use the statement checkAnyFrameChanged(top.frames). Here is an example of using the checkAnyFrameChanged function:

if(checkAnyFrameChanged(top.frames)) {
// something changed
} else {
// nothing changed
}

If you use one of the check*Changed functions to display a custom message, then be sure to consider internationalization.

The check*Changed functions have similar parameters to the saveWarning function. This is because the saveWarning function calls several of the check*Changed functions using the parameters passed to the saveWarning function.

11 comments:

"Hey! U r a real cool guy you!", i said to myself! said...

Very useful! Thanks!!!

kjps said...

Hi Jim

This may be quite offroad to the topic above but was wondering if you could help me.

We are trying to achieve autosave for eperformance module and after trying all the javascripts and ajax and other methods we have come up with this solution that works quite well except for a samm issue.

The requirement is to autosave if the user session has been idle on the eperformance pages and then do a timeout after 2 minutes of the save.


We followed the approach to force an autosave when the pagetimeout warning message is displayed and then force a timeout after the next 2 minutes.

The issue is that the code works fine on say JOB data component(removing the page name and changing the button name in the document.getelement id) but for the eperformance pages mentioned below it only saves but does not timeout.

Also if I remove the settimeout and do a simple self.location=timeouturl the data is not saved as the timeout is immediately fired.

To sumup :
1) adding a delay does not trigger timeout on the epreformance pages, without the delay the timeout occurs but the data is not saved.


/*** added the following code to PS_SAVEWARNINGSCRIPT
/***** beginning of custom code ****/
currurl=strCurrUrl;
pagepos=currurl.search("&PAGE");
remstring=currurl.substring(pagepos);
var myRegexp=/=/;
equalpos=remstring.search(myRegexp);
pagestring=remstring.substring(equalpos+1);


//alert("pagestring :" +(pagestring));
document.getElementById('EP_BTN_LINK_WRK_EP_STORE_PB').click();
//document.getElementById('#ICSave').click();
setTimeout("self.location = timeOutURL", 120000);
//self.location = timeOutURL;

/***** end of custom code ****/

timeoutWinOption = "toolbar=0,location=0,directories=0,status=0,menubar=0,scrollbars=0,resizable=0,width=330,height=220";
timeoutWin =window.open( timeoutWarningPageURL, "timeoutWarning", timeoutWinOption, true);
timeoutWin.focus();
}

function getForm(document,formname)
{
var objForms = document.forms;
if (!objForms)
return null;

Jim Marion said...

@kjps, the setTimeout timer is only valid as long as the page is loaded. If the page is reloaded, then the timer is discarded. I'm not familiar enough with ePerformance to know, but is it possible that the page is reloading? If you are on PeopleTools 8.49 or earlier, then it is guaranteed that a save will reset the timer. If you are on PT 8.50 or later, then it is questionable, depending on whether the page uses ajax or not. Normally just the transaction page refreshes, not the full frameset. It might be possible to set the timer on the parent or top windows as in:

parent.setTimeout(function() {self.location = timeOutURL}, 120000);

I also recommend using an anonymous function as shown here instead of a string command. This is because of scope. You want the variable to be visible at the location where the code runs. A closure keeps the variable in scope, but a string command won't.

Stephen said...

Hi Jim, I came across this post while looking for info on an "undocumented" peopletools feature that allows you to enable or disable the Save Warning via Peoplecode. I've used it before, in Tools 8.4 (8.47 maybe?) but I've forgotton the name of the function. Do you happen to know it? Also, being the grammar nazi, I think it should be "lose" rather than "loose", unless American differs from Australian on this. :-)
Cheers,

Stephen

Jim Marion said...

@Stephen, yes, it should be lose. Sorry. Well done.

I have to admit that I don't know about this feature.

David Vandiver said...

@Stephen, there is a rowset property called SetComponentChanged that might help.

Example: &rsWork1.SetComponentChanged = False;

David Vandiver

David Vandiver said...

@Stephen, I also found the following, which may be the undocumented feature you spoke of.

SetSaveWarningFilter(True);

True disables the SaveWarning and False enables it.

Credit goes to Dan Kibler who commented on this at:

http://getlevel0.blogspot.com.au/2011/01/debugging-save-warning.html

Supriya Katiyal said...

Hi Jim.

We are looking for auto save functionality in e Performance pages wherein auto save should not reset the timer for time out.

What we are trying to achieve :
I am trying to pass a variable such that even after forcing the Autosave, the time-out should not get affected
Eg: If I login at 10:00 AM, the autosave happens at 10:05 AM, the system time-out should still happen at 10:20 and not at 10:25 AM

We are at PTools 8.51.24 and Application version 9.1.

Jim Marion said...

@Supriya, when you auto save, that hits the web server and resets your timeout on the web server. The local browser version stored by PeopleSoft in JavaScript variables (warningTimeoutMilliseconds and totalTimeoutMilliseconds) is just there to call the timeout warning and expire URL's.

You can maintain your own copy of the timeout and keep it updated by either modifying your auto save code (if custom) or monkey patching net.ContentLoader if you are using delivered code to implement auto save. That way if the auto save resets the timeout, you still have another timeout set to expire the session that isn't updated.

Steve said...

Hi Jim, wanted to know that your blog post is still being used to help people many years after you wrote it!

Question, I'm using the saveWarning function as you detail here, which is working like a charm, EXCEPT when the window is closed by user.

following is what I'm doing, any idea how to get this to work including a window close event?


window.onbeforeunload = function() {
saveWarning('',null,'_self','');
}


Thanks!!

Steve

Jim Marion said...

@Steve, did you look into attachEvent and addEventListener instead of the method you used for event binding? One thing that might be happening is that your event binding is getting erased/overwritten on a PeopleTools Ajax request.