1

I have a web application that displays an overlay only when the page is loading (some server work). It works fine in Firefox and Chrome. For example when I login: i fill in the login form, then I click the login button, the overlay appears - while the server checks, then after a moment, another page is served or an error message is displayed.

The overlay won't display using Safari.

HTML code

<div class="overlay"  style="display: none;" id="loadingDiv">

javascript - jquery

 window.onbeforeunload = function(e) { $("#loadingDiv").show(); };

In safari: when I manually comment out the HTML initial hidden state - it shows. (That indicates that my CSS is alright.) But that's not how it should function.

I tried using opacity: 0 instead and the whole page is frozen.

How I get the overlay to appear only on page loads - like in Chrome?

Siavas
  • 4,992
  • 2
  • 23
  • 33
  • 1
    possible duplicate? https://stackoverflow.com/questions/14645011/window-onbeforeunload-and-window-onunload-is-not-working-in-firefox-safari-o - doesn't look like safari supports it: https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onbeforeunload – Pete Jan 25 '19 at 15:33
  • instead of `onbeforeunload`, why not do the server check using `jQuery.ajax`, by showing the overlay onsubmit, then redirect to another page or error page on success callback? – yqlim Jan 25 '19 at 15:42
  • @YongQuan I'll try. Can you please provide an example? – Yuma Technical Inc. Jan 25 '19 at 15:48

3 Answers3

1

Might be worth using a display attribute...

here I use JS to hide the div on load then when you click the button the div is made visible by removing the hide attribute

     $(document).ready(function () {
        //on page load
        //Adding the attribute and hides the div
        $("#loadingDiv").attr('hidden', 'hidden');
        //on a button click (this could be any event)
        $("#ContanerName").on("click", "#btn", function () {
          //removes the attribute and makes it visable
          $("#loadingDiv").removeAttr('hidden');
        });
      });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="ContanerName">
      <div class="overlay" id="loadingDiv">
        <p>hello world</p>
      </div>
      <input type="button" id="btn" value="button"/>
    </div>
Tom
  • 343
  • 2
  • 7
  • Thanks for the response. Although it's a good idea, the overlay is supposed to be displayed on each and every page load - not just for the login. Because others wrote most of the code, I cannot modify every (100s) click-action (mostly – Yuma Technical Inc. Jan 25 '19 at 17:40
  • Add the JS code to the master page or if your using MVC it will be the _layout page you need. This will then be user across the entire site. – Tom Jan 28 '19 at 14:51
1

It seems onbeforeunload is not supported by Safari, but the recommended approach in MDN is:

window.addEventListener("beforeunload", function (e) { 
    $("#loadingDiv").show();
});

This script has to be placed after loading jQuery, and preferably at the end of the <body> tag. Even better, wrap it with .ready() so that it is executed once the entire DOM has been loaded:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<div style="display: none;" id="loadingDiv"><div class="loader">Loading...</div></div>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
$(document).ready(function(){
    window.addEventListener("beforeunload", function (e) { 
        $("#loadingDiv").show();
    });
});
</script>
</body>
</html>

This was tested in Safari 12, Chrome 71 and Firefox 64.

Siavas
  • 4,992
  • 2
  • 23
  • 33
  • My HTML looks like: ... ... What is missing? – Yuma Technical Inc. Jan 29 '19 at 15:55
  • OK the only difference now is jQuery is loaded in the section and the application uses an old version (1.2). JQuery is only for the $().show right? and $().ready. So will it work with plain js? – Yuma Technical Inc. Jan 29 '19 at 16:34
  • @YumaTechnicalInc. didn't notify you yet as there is a different behaviour when trying to manipulate the DOM (as in, trying to show some content). Looking to find whether this is possible or not allowed in Safari. – Siavas Jan 29 '19 at 16:36
  • In the meantime try with the following snippet and look at the Developer Console to see that the event is being handled: `window.addEventListener("beforeunload", function(e) { console.log('Leaving page...'); });` – Siavas Jan 29 '19 at 16:38
  • it responded "undefined". And nothing happened on another page load... FOR YOUR INFORMATION $("#loadingDiv").show(); responded: {0:
    , length: 1, context: #document, selector: "#loadingDiv", init: function, jquery: "1.2.6", …} = $1 and the overlay showed.
    – Yuma Technical Inc. Jan 29 '19 at 16:42
  • Which Safari version are you using? I also have to mention that this may not work on snippet websites such as jsfiddle. Have you tried it on your environment? – Siavas Jan 29 '19 at 16:43
  • Safari 12.0.2 MacOS Mojave – Yuma Technical Inc. Jan 29 '19 at 16:45
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/187505/discussion-between-yuma-technical-inc-and-siavas). – Yuma Technical Inc. Jan 29 '19 at 16:47
  • @YumaTechnicalInc. how did this go finally? It seems the chat page is not found for some reason, shall I make the suggestions mentioned in the chat here in the post as well? – Siavas Jan 29 '19 at 21:45
  • Sorry for the delay. It seems like when I allocated the bounty, the chat closed???? Anyway I decided that my only option was to add code to handle form submissions and some clicks.. It works OK, but further clicks may need handling. I will try to post my code below... – Yuma Technical Inc. Feb 01 '19 at 20:09
1

After chatting with Siavas. I decided to handle action for form submissions and some clicks to trigger the overlay.

Here is my resulting javascript:

function init() {
    var forms = document.forms;
    for (var i = forms.length - 1; i >= 0; i--) {
        forms[i].onsubmit = function() {
            $("#loadingDiv").show();
        };
    }
    var subnav = document.querySelectorAll("ul.subnav li a");
    subnav.forEach(link => {
        link.addEventListener("click", function () {
            $("#loadingDiv").show();
        });
    });
}
document.addEventListener('readystatechange', function() {
    if (document.readyState === "complete") {
        init();
    }
});

At the bottom, a listener is added, upon being ready the init function is executed. The overlay is shown for each form submission. Then a listener is added for clicks (on ul.subnav > li > a) that also shows the overlay. This works in all browsers. Like Tom was showing.