Skillbuilders save before exit with Skillbuilders modal page - plugins

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:::::

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

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!

Related

How to display a form in modal dialog on page load?

This is on Drupal 8.6, PHP 7.2, Theme is based on Bootstrap.
The scenario is, I want to display a dialog box with a subscription form in the home page. The dialog box will be loaded automatically when page load, not by click any link.
I see there are lot of examples there in the net, but all related to by clicking a link, modal will display. But I want to load it without any click.
I partially successful by using BootstrapDialog, but ajax is not working on form submit button. What I did, I attach a js file in the front page, with the code below. It shows the Modal Dialog box, and I tuned a page--newsletter--subscribe.html.twig, its working But submit button not working not ajax is working.
BootstrapDialog.show({
title: 'Subscribe To Newsletter',
message: jQuery('<div></div>').load('/newsletter/subscribe'),
closable: false,
draggable: true,
closeByBackdrop: false,
closeByKeyboard: false,
buttons: [{
label: 'Close',
action: function(dialogRef){
dialogRef.close();
}
}]
});
I saw there is an example in code node.preview.js file like this:
var $previewDialog = $('<div>' + Drupal.theme('nodePreviewModal') + '</div>').appendTo('body');
Drupal.dialog($previewDialog, {
title: Drupal.t('Leave preview?'),
buttons: [{
text: Drupal.t('Cancel'),
click: function click() {
$(this).dialog('close');
}
}, {
text: Drupal.t('Leave preview'),
click: function click() {
window.top.location.href = event.target.href;
}
}]
}).showModal();
But I never able to make it working in my custom module.
If some one can help on this, will be really great!
Update:
I just tried to put a link manually in the template and tried to open the dialog, but it gives me some error:
Show Dialog
The error is as follows:
dialog.js?v=8.6.4:35 Uncaught TypeError: $element.dialog is not a function
at openDialog (dialog.js?v=8.6.4:35)
at Object.dialog.showModal (dialog.js?v=8.6.4:52)
at Drupal.AjaxCommands.openDialog (dialog.ajax.js?v=8.6.4:96)
at Drupal.Ajax.success (ajax.js?pkvhqx:155)
at Object.success (ajax.js?v=8.6.4:234)
at i (jquery.min.js?v=3.2.1:2)
at Object.fireWith [as resolveWith] (jquery.min.js?v=3.2.1:2)
at A (jquery.min.js?v=3.2.1:4)
at XMLHttpRequest.<anonymous> (jquery.min.js?v=3.2.1:4)
It seems some of the library is not loaded. Here is my global attachement:
dependencies:
- core/jquery
- core/jquery.ui
- core/drupal.ajax
- core/drupal
- core/drupalSettings
- core/drupal.dialog
- core/drupal.dialog.ajax
- core/jquery.form
- core/jquery.once
- core/modernizr
Any help will be great!
This issue is related to the pro theme I have purchased named "glazed". Its removed the bootstrap modals library. When I disabled the Bootstrap Modal library from theme settings, Modals are working fine. But when I tried to enable the Bootstrap Modal, it gives the following message, which explain everything:
Your theme is trying to load the Bootstrap Modals override library from the bootstrap basetheme. This library is not compatible with Glazed Builder and therefore its assets have been removed from the page. To make this message disappear Please go to your (default) theme settings form, scroll down to Bootstrap settings, and under the Javascript category disable the "Bootstrap Modals" setting.

Opening dialog on showing sap.m.Page

Having some trouble opening a Dialog after navigating to a page. The intention is to always open the dialog when a user lands on this page.
Simplified, I have a controller that looks like this:
onInit: function() {}
this.myRouter.getRoute("orderscreate").attachPatternMatched(this._onObjectMatched, this);
},
_onObjectMatched: function() {
this.dialog = sap.ui.xmlfragment("myDialog", this);
this.dialog.open();
},
When I put a debugger in, this works great: I can see the dialog is open.
THEN, the navigation animation kicks in, does the slide animation, and upon completion the dialog is closed again. I'm not sure why it insist on navigating after the view has rendered.
This happens when using navTo as well. Dialog opens, animation starts, dialog is closed again. sap.m.Page does not have another way of executing code after showing, as far as I'm aware.
Any advice?
Unless told otherwise the TargetHandler will close all open dialogs.
TargetHandler, a class used for closing dialogs and showing transitions in NavContainers when targets are displayed.
Try adding the following code after your router has been initialized
this.myRouter.getTargetHandler().setCloseDialogs(false);

How to detect if side menu is open/closed in ionic 2?

I am using cordova-google-maps plugin with my ionic 2 app, and I want to show the menu (sidenav) on that page. Problem is for the sidenav to receive events properly I need to call map.setClickable( false ) while opening the sidenav and set it back to true when the user closes the sidenav. It seems there is an event for checking while the menu is being opened with opening, but I don't know how to track when the user closes the menu.
For using ionDrag, ionOpen, ionClose in Ionic2 you must add it on the menu itself
for example modify menu in your app.html file by
<ion-menu [content]="content" (ionOpen)="menuOpened()" (ionClose)="menuClosed()">
After I use "Events" see doc here: http://ionicframework.com/docs/v2/api/util/Events/
For detect in my page if the menu was close or open.
Example in my app.ts
menuClosed() {
this.events.publish('menu:closed', '');
}
menuOpened() {
this.events.publish('menu:opened', '');
}
And in my other page
events.subscribe('menu:opened', () => {
// your action here
});
events.subscribe('menu:closed', () => {
// your action here
});
I hope this help
It seems new events have been added to the menu component which solves this problem. I am also using the google maps plugin and it works fine
http://ionicframework.com/docs/v2/api/components/menu/Menu/
ionDrag
When the menu is being dragged open.
ionOpen
When the menu has been opened.
ionClose
When the menu has been closed.
Using these output events, in your handlers you can keep a flag for the menu if its open or not :)

How to detect if a hyperlink has been clicked in a WebView in Metro?

Is there anyway i can get the hyperlink click in webview to my c# with Hyperlink value in Metro?. I am using WebView..NavigateToString() to generate the content?.
You can call InvokeScript with some of your own Javascript to set up a listener for when the user navigates away from your page. This would look something like the following in C#:
var navigationListenerString = #"
(function() {
function leavingPage() {
window.external.notify("LEAVING PAGE");
}
window.onbeforeunload = leavingPage;
})()";
webView.InvokeScript("eval", new string[] { navigationListenerString });
Then you can use ScriptNotify to listen for your particular message to determine that the page is unloading and the user is leaving. Unfortunately you cannot detect where a user is going. Also, if the hyperlink opens in a new window and the webview does not unload, you cannot detect that either.
Since WebView in windows 8 doesn't support Navigating() events like the Silverlight WebBrowser control, thus it is not possible to get hyperlink or cancel navigation.
But since you're using NavigateToString() method, you can write some manual javascript code and achieve same with the help of WebView.ScriptNotify() event.

How to create a "New xxx" popup?

I have a Grid object and added a [ (+) New Client ] button which I'd like to open a popup form to create the new client with a couple fields.
I've looked at the code examples in the website but haven't found how to do it (sorry if I've missed something).
This is the current page code:
function page_clients_listing($p){
$g = $p->add('Grid');
$g->addColumn('text','first_name');
$g->addColumn('text','last_name');
$g->addColumn('inline','telephone');
$g->addColumn('expander','comments');
$g->setSource('client');
$g->addButton('With Icon')->set('Add New Client')->setIcon('Plus');
}
Thanks in advance!
You can either create a popup or a dialog. Dialog is based on jQuery UI dialog implementation. Popups are likely to be blocked and are harder to control.
This is actually working for any object (you can apply to view, button, image, icon, etc), but I'll use button).
$b=$g->addButton('Add New Client')->setIcon('Plus');
$b->js('click')->univ()->frameURL($title,$url);
// OR
$b->js('click')->univ()->dialogURL($title,$url);
$url would most likely be returned by api->getDestinationURL(). The other page would be loaded and scripts on that page will be evaluated. Let's say you are on other page and now need to close the window.
$result = $this->addButton('Close')->js('click')->univ()->closeDialog();
closeDialog() returns a jQuery chain object pointing to a view which originally opened the frame. As a result if you do $result->hide(); then after dialog is closed, the original button ('add new client') will also be hidden.
Here is example to show some additional things you can do with frames, reloading and custom event handlers:
http://agiletoolkit.org/example/refresh1