How to trigger 'beforeunload' event from within an IFRAME - javascript

I have an application (name it B) which is being embbeded in an Iframe by another main application (Name it A or parent).
So: App A-- // domain of A: https://mydomain/mainApp
|___ App B in Iframe // domain in B: https://mydomain/appB
Problem is: Then main/parent app has a navigation menu. One item, when clicked, creates an Iframe with SRC ATTRIBUTE loading App B inside.
When the user clicks into another option of the menu in app A, the Iframe is destroyed and another content View in React appears, replacing the Iframe.
When doing this, all data typed in forms by the user in B are gone, as I can not trigger a save event I have in B.
I have added following event handler in the iframe app:
window.addEventListener("beforeunload", function (e) {
// Trigger here the save settigns event inside B
});
But former code is never triggering when user navigates through Main App menu. As I can see, navigating menu in App A, changes URL in the browser(but seems a SPA React.js routing or similar, no real redirection).
Question is: Can Iframe detect when is going to be unloaded/destroyed to trigger first the Saving Settings in Ajax ? P.S: I don't have access to App A code.
Thanks in advance

From MDN:
The WindowEventHandlers.onbeforeunload event handler property contains the code executed when the beforeunload is sent. This event fires when a window is about to unload its resources. The document is still visible and the event is still cancelable.
The unload event is fired when the document or a child resource is
being unloaded. It is fired after:
beforeunload (cancellable event)
pagehide
Example:
<body>
<input type="button" id="removeIframeBtn" value="remove iframe"/>
<iframe id="iframe" src="http://localhost:8080/iframe.html"></iframe>
</body>
<script>
const removeIframeBtn = document.getElementById("removeIframeBtn");
const iframe = document.getElementById("iframe");
iframe.contentWindow.onbeforeunload = function () {
debugger;
};
window.onbeforeunload = function () {
debugger;
};
removeIframeBtn.onclick = function () {
iframe.remove();
};
</script>
Let assume that page with current code is opened in the browser tab.
If you try to close this tab, iframe.contentWindow.onbeforeunload will be called.
If you try to click on remove iframe btn, iframe will be removed from document but iframe.contentWindow.onbeforeunload will not call. There is no unload event.
React renders components with js, so it is totally like second case with clicking on remove iframe btn.
So the answer on your question is: it is not possible to detect unloading of iframe with onbeforeunload event in single page application on route changing.
Solution for you can be to save settings on every its change.

unload event works so you can do
IframeWindow.addEventListener('unload', ()=>{
debugger
})

Related

How to ensure that all onclick events on clicked domnode got executed before the page navigates to another page

We are working on an Open Source Chrome extension: Digital Assistant Client
Product Demo:
Part 1: https://www.youtube.com/watch?v=Iz2WgKY0fhc
Part 2: https://www.youtube.com/watch?v=i0_MNfBnYfM
We are having trouble in getting our onclick event handler executed when the page is navigated to another page.
I want to invoke all the onclick event handlers attached to a domnode that the user has clicked before the page gets navigated to another page so that our functionality gets executed. The solution should work for any framework that cancels the bubbling of the onclick event handlers.
There are some questions already raised by some people as given below
How to ensure that a function is executed completely, before navigating to another page?
How to execute onclick before navigating to a different page?
Thanks in advance
You can probably monkey-patch addEventListener on the DOM Node, capture the event handlers that get registered later, and maintain a list of those.
const originalEventListener = DOMNode.addEventListener;
DOMNode.addEventListener = (type, callback) => {
const clicksHandler = [];
if(type === 'click'){
clicksHandler.push(callback);
originalEventListener.call(DOMNode, type, callback);
}
}
You can probably use beforeunload event to make sure all the clicksHandler are called once again before user navigates away.
window.onbeforeunload = (e) => {
clickHandler.forEach((handler) => handler.call(...))
}
you just have to call the event on that element.
const button1 = document.getElementBy....
button1.click()
add alert before navigation inside click method, so alert will notify you.

Open a popup automatically and prevent browser to block it

I need to call a function (which one will open a popup) when my page is loading.
If I want the popup to be open, the function should be called by a user event (a click or something).
I tried to simulate the click event but it's not isn't working. The function is being called but no click event has been created.
For example, I tried with angular to do the following:
var element = angular.element("<div ng-click='MyFunction()'></div>");
compiled = $compile(element)(scope);
$timeout(function () {
compiled.triggerHandler('click');
}, 100)
#IsraGab,when you want an user event when page loads then i think you must go for onmouseout Event for body element.
here is plunker link:
Plunker

WinJS Stop javascript in memory

I'm learning using the Win.JS navigation and I am able to navigate between pages now. But I'm having errors when I leave a page and trigger a event from the first page.
So the problem is. I have some javascript running on Page1.html | .js
If I press the Arrow up button on my keyboard for example a javascript runs (onclick). This works okay, but then I click on a button and navigate to Page2.html also with a ( .js) and if I then also click on the Arrow up button I get an error. It tries to start the function that is called within the onclick, and that isn't there anymore in my Page2.
So the question is, how can I unload these javascript triggers from Page1 if i'm notttt on that page anymore?
In your WinJS Page definition you can define unload method that is always invoked when the user leaves the page. Unregister all event handlers there.
WinJS.UI.Pages.define("/page.html", {
ready: function (element, options) {
// add onclick handler
},
unload: function() {
// remove here all event handlers
}
});

Attach DOMContentLoaded listener to dynamically created window

Due to how some of our pages work, JS can get injected into the page at any point and sometimes this JS closes the current window. The problem is that I need to attach an event listener to the onunload of the window so that a value may be returned from the window to the parent page. But because the window close script may be injected at any point, I can't bind this event to the onload due to how it works so I was hoping to use DOMContentLoaded since that event will trigger before the injected script does.
However in my tests, I cannot get anything to bind to DOMContentLoaded on the parent page where the new window is being created.
Here is an what I am currently working with: Plunker
We only need this to work in Chrome at the moment.
Our current method of doing this works like this (pseudocode):
onButtonClick = function(){
win = window.open(...);
win.onload = function(){
win.onunload = function(){
//Bind some function that will get the window's "return value" and pass it to the parent page
//This will never happen if the window closes itself before the page is done loading
};
};
};
Can I use DOMContentLoaded to accomplish what I want? If so, how do I properly attach it to the window?
Note: I cannot bind the onunload event directly to the window once it is created. It seems to fire the onunload event twice (once when the window opens and once when it closes). You can see this happening if you use the bindOnCreate function in my example.
If you change line 58 from
w.document.addEventListener('DOMContentLoaded', ...)
to
w.addEventListener('DOMContentLoaded', ...)
it works. I'll try to explain what's actually going on under the hood:
When window is opened, it is initially having URL about:blank. You can check this by logging w.location.toString() in onunload event handler (see next step).
Immediately after that the browser loads URL supplied in window.open, thus triggering onunload for about:blank (first time).
Real page with different window.document is loaded into pop-up window, but your event handlers are still listening to the DOM root of about:blank page because you added events to window.document, not window; and right now as we have another URL loaded, window.document is completely different object than one step before.
When you close window, onunload is triggered again (second time) because your onunload event was connected to window.
If you addEventListener for pop-up's window, it receives events from all window.document-s that will be loaded inside that window because of JS event bubbling mechanism.
I hope this answers your questions.
Alternatively, you can send a message from the child window to its opener, rather than let opener to handle child window's unload event. This will be much easier and you don't need to worry about the injection point. Also you can get rid of twice unload event, as Andrew Dunai has already given the reason for this issue.
Here I give a very simple demo, only shows the skeleton of my messaging solution:
parent.html
<button id="open">Open Window</button>
<button id="close">Close Window</button>
<div></div>
<script>
var child;
document.querySelector('#open').addEventListener('click', function() {
document.querySelector('div').innerHTML = '';
child = window.open('child.html', 'child', 'width=600,height=600');
}, false);
document.querySelector('#close').addEventListener('click', function() {
child.close();
}, false);
window.addEventListener('message', function(e) {
document.querySelector('div').innerHTML = e.data;
}, false);
</script>
child.html
<input type="text" value="" placeholder="input something">
<script>
window.addEventListener('beforeunload', function() {
var msg = document.querySelector('input').value;
window.opener.postMessage(msg, '*');
}, false);
</script>
Either you close child window by click its own window's close button, or the button in parent window, the value in child's input will always send to parent and presented.
This is the key approach for one of my side project, and works very well.

Detect tab/window activation in JavaScript

It seems that Google+ checks for notification updates when I activate the tab in Firefox
It'd show "0" every time I activate it, but change to a number of new notifications in a couple of seconds after that.
What's the mechanism allowing to tap into that event? Is there a specific DOM event for that? Or are they using something like onmouseover handler and just consider any kind of activity to be a sufficient indicator of tab activation?
Just a guess because I haven't all relevant browsers available for testing.
What about using the focus event on the window. Whenever a user clicks somewhere this is invoked but also on switching of tabs. To distinguish between a user's actions on the page and a user switching to the page you could check if the event's explicitOriginalTarget points to the window.
window.onfocus=function(event){
if(event.explicitOriginalTarget===window){
console.log('switched from tab');
}
}
There is Page visibility document, which describes document.onvisibilitychange event handler.
The usage
document.onvisibilitychange = function() {
console.log("Visibility of page has changed!");
};
Unfortunately there's no 100% accurate solution
onvisibilitychange correctly triggers on tab changes, but does not trigger on window changes (ALT+TAB) visibilitychange event is not triggered when switching program/window with ALT+TAB or clicking in taskbar
window.onfocus triggers when the document becomes focused. This works as expected if the tab's focus is already inside the web page, then it correctly triggers when window or tab becomes focused.
But if you have the focus on the URL bar, or in the console, you are already "out of focus", and when you get out of the window or tab and return, you will remain "out of focus", so this event won't trigger until you click inside the page, or navigate into it through TAB key
You can test below how each event triggers (click inside the white iframe to test onfocus/onblur events)
window.onfocus = () => console.log("focus");
window.onblur = () => console.log("out of focus");
document.onvisibilitychange = () => console.log("visibilityState: ", document.visibilityState);

Categories