1
votes

I am having troubles trying to understand how to use "Save before Exit" plugin with the Modal Page plugin in Oracle ApEx v4.1.1.

I basically would like to know how to attached the 'X' close button to the "Save before Exit" plugin when a user makes a change to a select list or text area field on the page (I also have classes associated to these fields), used within the modal page?

Here are links to the two plugins that I am trying to link together:

http://apex.oracle.com/pls/apex/f?p=46685:MODAL_PAGE:0

http://apex.oracle.com/pls/apex/f?p=46685:SAVE_BEFORE_EXIT:0:::::

2
you want to check if there are unsaved changes when the user closes the modal page by clicking the modal dialog close button? - Tom
Hi Tom - yes this is correct. Just unsure how to capture this if the user presses the close button by accident let's say. Any ideas? Have you used these plugins at all? THanks. - tonyf
I'm familiar with the plugins, i've used the modal one a lot. Save before exit not so much. I've now spent quite some time on trying to nicely integrate both, but it's proving to be a serious PITA. Most of the hurt is because of how save before exit works: it is an onbeforeunload event. It does fire in FF, but only late after the facts: colorbox (modal popup) has already removed the markup at that point. I'll post some of my findings/ideas later on. - Tom

2 Answers

1
votes

Important note: i tested this plugin with the latest version available: 3.0.2. The change detection routine there is modificationDetected, where in 3.0.0 it was changeDetected! Check which version you use!


When i have to integrate things like these, i want to avoid altering provided code such as the plugin code. Doing this will break your stuff if you don't remember in the future and install a new version (unless you're actually fixing something of course).

Create a dynamic action on the page that calls the modal dialog, fire on load:

var default_colorbox_close = $.colorbox.close;
$.colorbox.close = function(){
   iframejQ = $("iframe").get(0).contentWindow.apex.jQuery;
   iframeDoc = iframejQ($("iframe").get(0).contentWindow.document);

   apex.debug("Colorbox close attempt - check changes");
   var hasChange = iframeDoc.apex_save_before_exit("modificationDetected");
   apex.debug('Modal contains changes: '+hasChange);

   if(hasChange){
      $( "<div title='Unsaved changes!'>There are unsaved changes. Close the popup anyway?</div>" ).dialog({
         resizable: false,
         height:140,
         modal: true,
         stack: true,
         zIndex: 9999,
         buttons: {
            "Don't close": function() {
               $(this).dialog( "close" );               
            },
            "Close": function() {               
               iframeDoc.apex_save_before_exit("disableWarning")
               default_colorbox_close();
               $(this).dialog( "close" );
            }
         }
      });
   } else {
      apex.debug('Close modal with default colorbox close');
      default_colorbox_close();
   };
};

The save before exit plugin works by using the browser window.onbeforeunload event. It does trigger when the popup is closed (at least in FF it does), but by then it is way too late: the popup is gone and the markup too.
My first thought was to simply tap that onbeforeunload event by redirecting the page to a generic page which would hold onload code to close the popup. The onbeforeunload would spring in action as soon as the redirect would be attempted. There would be no dynamic action or plugin altering. But oh well, i decided against that. (Note though: most of the code in this snippet would have to be reused in that case too, save change detection and dialog).
Instead i choose to check for changes in the iframe document when a close event happens, and display a dialog, which can be modified too, and clearly indicates that you are performing an action on the popup and not on "the page" (which could be interpreted as the parent page of the modal).

So what is needed is to catch the modal popup close event. Note that the plugin is based of the jQuery Colorbox plugin. The Skillbuilder modal does not provide a pre-close event and can not without altering the colorbox plugin.
Colorbox provides a close option in the form of the "X" and also the ESC-key. I want to catch both(/all).
I didn't opt for unbinding the click on the X and binding a new click.

  • what i did first is save the default colorbox close event, and then override the default.

     var default_colorbox_close = $.colorbox.close;
     $.colorbox.close = function(){
    
  • Next up: this piece of code will get the jQuery instance of the modal page. I then fetch the document element of the page with this jquery instance

     iframejQ = $("iframe").get(0).contentWindow.apex.jQuery;
     iframeDoc = iframejQ($("iframe").get(0).contentWindow.document);
    
  • Next up is checking the iframe (modal popup) for changes

     var hasChange = iframeDoc.apex_save_before_exit("modificationDetected");
    
  • So if the page has changes, a warning has to be displayed. I do this by using jQuery-UI Dialog. It will have "Unsaved changes!" as title, and 2 buttons ("Don't close" and "Close"). When closing, the save before exit plugin has to have its default warning disabled! If not, you'd still get prompted by the onbeforeunload message! Then the colorbox has to be closed (which will remove the iframe). Finally the dialog (prompt) has to be closed.

      if(hasChange){
         $( "<div title='Unsaved changes!'>There are unsaved changes. Close the popup anyway?</div>" ).dialog({
            resizable: false,
            height:140,
            modal: true,
            stack: true,
            zIndex: 9999,
            buttons: {
               "Don't close": function() {
                  $(this).dialog( "close" );               
               },
               "Close": function() {               
                  iframeDoc.apex_save_before_exit("disableWarning")
                  default_colorbox_close();
                  $(this).dialog( "close" );
               }
            }
         });
    
  • If there are no changes, then the modal can simply be closed.

      } else {
         apex.debug('Close modal with default colorbox close');
         default_colorbox_close();
      };
    

Hope some of that sticks ;)

Example on http://apex.oracle.com/pls/apex/f?p=11128:1


Edit:
And some big thanks to Dan McGhan for helping in the OTN thread :)
https://forums.oracle.com/forums/thread.jspa?threadID=2434115&tstart=0

1
votes

I would like to add something to the answer. I've noticed that the items that changed are not highlighted. So I've added this line to the "Don't Close" right before closing the dialog box.

iframeDoc.apex_save_before_exit('modifiedItems', {highlight:true});

And it highlights the items as it should!