SOLVED: Loading.gif displayed until <webview> contents are fully loaded


#1

I’d like to have loading.gif displayed until my webview is loaded. Currently, I have an index.html that has a sidebar…and when a sidebar link is clicked…it opens a seperate html file that contains a to the URL I am intending to go to.

<!-- Sidebar -->
        <div id="sidebar-wrapper">
            <ul class="sidebar-nav">
                <li class="sidebar-brand">
                    <a href="#menu-toggle" id="menu-toggle">
                        <img src="./gs_logo.png" style="width:42px;height:42px;border:0;">
                        Sample Inventory App
                    </a>
                </li>
                <li>
                    <a href="#gpage" onclick="loadFile('./inventory.html');">Inventory</a>
                </li>
                <li>
                    <a href="#gpage" onclick="loadFile('./customers.html');">Customers</a>
                </li>
                <li>
                    <a href="#gpage" onclick="loadFile('./locations.html');">Locations</a>
                </li>
                <li>
                    <a href="#gpage" onclick="loadFile('./orders.html');">Orders</a>
                </li>
                <li>
                    <a href="#gpage" onclick="loadFile('./settings.html');">Settings</a>
                </li>
                <li>
                    <a href="#gpage" onclick="loadFile('./logout.html');">Logout</a>
                </li>
            </ul>
        </div>
        <!-- /#sidebar-wrapper -->

Two Questions:

  1. Would it be easier to load the each URL inside of index.html instead of using loadFile to open external html files?
  2. I use the following code to display loading.gif, but it only shows up briefly until the internal html file is loaded (it disappears before the contents have a chance load…the it still feels like a slow webpage instead of native app). How do I have loading.gif stay visible until the URL inside of is fully loaded?
function loadFile(url){ $("#loading").css("display", "block"); $.ajax({ url: url, success: function(result){ $("#loading").css("display", "none"); // stop loading gif $("#gpage").html(result); } }); }

#2

So #gpage is your webview that you are setting the HTML in?

I see there is the obvious problem with this that you are hiding the loading animation before the webview has even begun to process the new page contents. According to the docs a window/webview has the “did-finish-load” event. I would try listening for this event on the webview and hiding the loading animation then.

http://electron.atom.io/docs/api/webview-tag/#event-did-finish-load


#3

#gpage” executes this script:

function loadFile(url){
("#loading").css("display", "block"); .ajax({
url: url,
success: function(result){
("#loading").css("display", "none"); // stop loading gif ("#gpage").html(result);
}
});
}

Basically, my app has a sidebar that navigates between 4 different URLs…and I have chosen to load the URLs using html files for that contain each url inside of a webview tag (this keeps the sidebar from flashing white). Is there a better way to do this? Here is a screenshot of the interface, which may shed some light on things:

If I’m understanding correctly, you’re suggesting the “did-finish-load” event is best to listen for. Does this mean that I might write the script for loading.gif inside of each html files (customers.html, etc.) instead of in index.html?


#4

The docs page about webview has an example of using a loading indicator.

Hmm, I’m getting a bit confused about where your webview is. So your webview is not in the index.html, it’s in each of your loaded HTML files? If so, then my thoughts are as follows.

If your webview is in each loaded file then it is having to create a new webview with every page load, which means instantiating a whole new chrome process each time. That will slow things down?

Maybe your requirements mandate a new webview each time, but if it was me I’d do it like the following.

index.html:

<html><body>

<div id="sidebar">
  <p><a href="https://mydomain.tld/customers.html" class="sidebar_link">Customers</a></p>
  <p><a href="https://mydomain.tld/locations.html" class="sidebar_link">Locations</a></p>
</div>

<div id="page_wrapper">
  <webview id="page"></webview>
</div>

<script type="text/javascript">
function show_loading_animation()
  {
  // Manipulate DOM.
  }

function hide_loading_animation()
  {
  // Manipulate DOM.
  }

$(document).ready(function()
  {
  var webview = $('#page')[0];

  $('.sidebar_link').on('click', function(e)
    {
    e.preventDefault();
    webview.loadURL($(this).attr('href'));
    }
  );

  webview.addEventListener('did-start-loading', show_loading_animation);
  webview.addEventListener('did-stop-loading', hide_loading_animation);
  }
);
</script>

</body></html>

I’ve put full URLs in the links because I don’t know if the webview could properly figure out relative URLs in this particular use case.

Keeping just one webview constantly active and telling it to load different URLs also means you could easily implement backwards and forwards navigation if you wanted to.


#5

Wow, excellent work @erikwallace-lewdewe! I updated my index.html per your specs and my pages load twice as fast as they did before! I did not realize that I was initiating new chrome processes every time an html file was loaded onclick.

Also, your suggestion to utilize ‘did-start-loading’ and ‘did-stop-loading’ worked like a charm. Great advice, you really helped get us over a major UX issue.

Now, to figure out how to load a splash.html at application launch and ship the product. Thanks again!


#6

You’re welcome. :+1:

Yep, a webview is really just an embedded window, like an iframe. So every time the HTML parser encounters another webview tag it causes similar resource consumption and processing as when you tell your browser to open a link in a new tab or window - and for Chromium every view is a separate process at the OS level.

Depends on what you need for the splash page. You could just supply it as your URL to the window when it is created, when you are ready to show the interface then the window simply moves on by loading index.html.


#7

Looking at it now, I guess the loading.gif may be sufficient. I originally just wanted a 3 second intro screen to appear before index.html loads with the webview (something similiar to onload="splash(3000)). Is there a way to accomplish this with a local file instead of CSS settings?

If I utilize the following in main.js, the user will need to take action before the splashscreen dissapears.

mainWindow.loadURL(url.format({ pathname: path.join(__dirname, 'splash.html'), protocol: 'file:', slashes: true }))

#8

You could have them take action or you can automatically redirect. There are two ways:

Meta tag:

<head>
<meta http-equiv="refresh" content="3;url=https://mydomain.tld/index.html">
</head>

Or Javascript:

setTimeout(function(){document.location = 'https://mydomain.tld/index.html';}, 3000);

#9

Both worked out very well. I think I’ll probably stick with the JS method. Thanks for the help!