How to check modal pop up visible or not. If not visible bypass the check - protractor

I am automating an angular based UI. After a successful login to main page, sometimes, based on some logic, a modal based TOUR pops up which is intermittent. I need to click on CANCEL if the modal pop up appears and if does not appears then proceed with rest of execution. But my code fails with
"ElementNotVisibleError: element not interactable"
when I use below code to validate if element is visible.
browser.switchTo().activeElement().then(function() {
browser.sleep(1000);
element(by.id("closeBtn1")).isPresent().then(function(text) {
if (text) {
element(by.id("closeBtn1")).element(by.xpath('span')).click();
}
})
});

Here is what you are probably looking for:
browser.wait(protractor.ExpectedConditions.visibilityOf($('modal-popup-selector')), 2000)
.then(async function () {
$('modal-popup-cancel-button').click(); // if modal did appear then close it
}, function () {
// do nothing if modal did not appear within 2000 msc.
});
This approach works well if you do not know what are pre-conditions for the modal to be shown, but on the other side it will take extra time (2000 msc) for each time the modal did not appear.
Check visibilityOf condition docs.

Related

How do I make a modal open only the first time a user visits the page?

I am using Bootstrap 5.0.2 as the basis of my website, I finally got the modal to appear on page opening, thanks stack overflow, my aim is to not have the modal appear should the visitor move to another page and then return.
This is the code for running the modal. What do I need to add to make it only function the first time this page is viewed per session?
<script>
window.addEventListener('DOMContentLoaded', () => {
const modal = new bootstrap.Modal(document.querySelector('#myModal'));
modal.show();
});
You would need to implement sessionStorage.
When a user visits the page, we check to see if the sessionStorage contains a value for the modal. If it is the first time they load the page, it would not contain a value as we haven't set anything to it yet. In that case, we show the modal as normal and set a value for the sessionStorage. That way, when the user refreshes the page the value is already set in sessionStorage so the if statement will not run.
window.addEventListener('DOMContentLoaded', () => {
if (!sessionStorage.getItem("modal")) {
const modal = new bootstrap.Modal(document.querySelector('#myModal'));
modal.show();
sessionStorage.setItem("modal", "blah");
}
});

Is there any way to pop several pages and reload the destination page?

I'm setting up an app which have to fill a long 4-part form, which might be displayed in 4 sequential screens in a mobile application. Now on the 4th part of the form, there is a submit button. User clicks on Submit and all the previous screens should be popped and user should be taken back to the Item-List screen(1st screen) where the updated data items must be shown. We won’t be pushing anything new here, just going back to a previous route. But the first page should be reloaded. How is this possible?
// Updated Answer
So if this is your first screen where you are pushing and where you want to call a function when poped, this is how you can do it.
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => RegisterScreen()))
.then((success) {
if(success){
// call your function here
}
});

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);

Toggle Entire Accordion Functionality with Link or Button

I have an accordion that works great. I'm trying to figure out a way to search all the flaps of the accordion:
Find String on Page (Ctrl+F) when jQuery Accordion in Use
I have used the destroy method on a link and then reinitializing on another link, but it would be great to toggle this with one button. ((I originally asked this question without this solution here, so the answer below is just this. I won't accept it until I see if any better solutions come up))
$(document).ready(function() {
$("#hide").click(function() {
$(".accordion").accordion("destroy");
});
$("#show").click(function() {
$(".accordion").accordion({
navigation : true,
collapsible : true,
heightStyle : "fill",
active :
});
});
});
I was also able to toggle the entire accordion with jQuery toggle() but this just makes the entire thing disappear. What I want is to toggle the accordion functionality, while leaving the div structure behind so it's visible, just as if someone disabled JavaScript in the browser.
So the above kind of does what I want, except in reality, the better solution is to actually remove the class .accordion because that makes the page truly look like it should. Destroying the accordion actually breaks some stuff and this is undesirable.
I thought it would be as easy as this but it's not working:
$(document).ready(function() {
$("#hide").click(function() {
$("#accordion").removeClass(".accordion");
});
$("#show").click(function() {
$("#accordion").addClass(".accordion");
});
});
This does seem to be adding and removing the class I'm telling it to, but the initial remove is not removing the accordion class to remove the accordion itself.
I have used the destroy method on a link and then reinitializing on another link (although one button toggle would be better):
$(document).ready(function() {
$("#hide").click(function() {
$(".accordion").accordion("destroy");
});
$("#show").click(function() {
$(".accordion").accordion({
navigation : true,
collapsible : true,
heightStyle : "fill",
active :
});
});
});
I had to edit some CSS to make this work out, but it's the best I could find.
NOTE
I should note that I ended up finding even a simpler approach to this. Simply adding a reload restores the page back to its original state:
$("#show").click(function() {
location.reload();
});
The destroy and reload is a very simple solution. The one button aspect is solved with this event which goes in the document ready function:
// event to destroy accordion and make it's content searchable
$("#open-1").on("click",function() {
// if the button says Enable reload to bring the accordion back
if ($(this).html() == "Enable") {
location.reload();
}
// otherwise destroy the accordion and change the button to Enable
else {
$("#accord-1").accordion('destroy');
$(this).html("Enable");
}
});
The button can say anything you want initially. The key is that it's set to "Enable" and tested for "Enable" to reload the page. You can make that any string you want as well. Here's a complete example.

Skillbuilders save before exit with Skillbuilders modal page

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!