Permalink
Browse files

Improved unload script to support user defined onbeforeunload function

and new navigator beacon API
  • Loading branch information...
1 parent 5f99eac commit 480727e7fe48547499c1ad50799df33360d0a6e9 @BalusC BalusC committed Nov 25, 2016
@@ -19,7 +19,7 @@
* @see org.omnifaces.cdi.ViewScopeManager
* @since 2.2
*/
-OmniFaces.Unload = (function(Util, window, document) {
+OmniFaces.Unload = (function(Util, navigator, window, document) {
// "Constant" fields ----------------------------------------------------------------------------------------------
@@ -37,8 +37,8 @@ OmniFaces.Unload = (function(Util, window, document) {
/**
* Initialize the unload event listener on the current document. This will check if XHR is supported and if the
- * current document has a JSF form with a view state element. If so, then register the <code>beforeunload</code>
- * event to send a synchronous XHR request with the OmniFaces view scope ID and the JSF view state value as
+ * current document has a JSF form with a view state element. If so, then register the <code>unload</code> event to
+ * send a beacon or synchronous XHR request with the OmniFaces view scope ID and the JSF view state value as
* parameters. Also register the all JSF <code>submit</code> events to disable the unload event listener.
* @param {string} viewScopeId The OmniFaces view scope ID.
*/
@@ -48,27 +48,33 @@ OmniFaces.Unload = (function(Util, window, document) {
}
if (id == null) {
- Util.addEventListener(window, "beforeunload", function() {
- if (disabled) {
- self.reenable(); // Just in case some custom JS explicitly triggered submit event while staying in same DOM.
- return;
- }
+ var form = getFacesForm();
- var form = getFacesForm();
+ if (!form) {
+ if (jsf && jsf.getProjectStage() == "Development" && window.console && console.error) {
+ console.error(ERROR_MISSING_FORM);
+ }
- if (!form) {
- if (jsf && jsf.getProjectStage() == "Development" && window.console && console.error) {
- console.error(ERROR_MISSING_FORM);
- }
+ return;
+ }
+ Util.addEventListener(window, window.onbeforeunload ? "unload" : "beforeunload", function() { // If there's no user-defined onbeforeunload handler, let's perform job during beforeunload instead, which is more reliable.
+ if (disabled) {
+ self.reenable(); // Just in case some custom JS explicitly triggered submit event while staying in same DOM.
return;
}
try {
- var xhr = new XMLHttpRequest();
- xhr.open("POST", form.action.split(/[?#;]/)[0], false);
- xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
- xhr.send("omnifaces.event=unload&id=" + id + "&" + VIEW_STATE_PARAM + "=" + encodeURIComponent(form[VIEW_STATE_PARAM].value));
+ var url = form.action.split(/[?#;]/)[0] + "?omnifaces.event=unload&id=" + id + "&" + VIEW_STATE_PARAM + "=" + encodeURIComponent(form[VIEW_STATE_PARAM].value);
+
+ if (navigator.sendBeacon) {
+ navigator.sendBeacon(url); // Synchronous XHR is deprecated during unload event, modern browsers offer Beacon API for this which will basically fire-and-forget the request.
+ }
+ else {
+ var xhr = new XMLHttpRequest();
+ xhr.open("POST", url, false);
+ xhr.send(null);
+ }
}
catch (e) {
// Fail silently. You never know.
@@ -119,4 +125,4 @@ OmniFaces.Unload = (function(Util, window, document) {
return self;
-})(OmniFaces.Util, window, document);
+})(OmniFaces.Util, navigator, window, document);
@@ -101,7 +101,7 @@ public void nonAjax() {
guardHttp(unload).click();
assertNotEquals(previousBean, previousBean = bean.getText());
- assertEquals(messages.getText(), "unload init");
+ assertEquals("unload init", messages.getText());
// Navigate then submit then unload.
@@ -115,7 +115,7 @@ public void nonAjax() {
guardHttp(unload).click();
assertNotEquals(previousBean, previousBean = bean.getText());
- assertEquals(messages.getText(), "unload init");
+ assertEquals("unload init", messages.getText());
}
@Test @InSequence(2)

0 comments on commit 480727e

Please sign in to comment.