Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OnNavigationStarted called multiple times after page load completes #129

Open
dczaretsky opened this issue Sep 17, 2019 · 1 comment
Open

Comments

@dczaretsky
Copy link

dczaretsky commented Sep 17, 2019

Hello,
I seem to be having a problem with OnNavigationStarted event in opening (external) website content. I'm using OnNavigationStarted to show the activity indicator, and then OnNavigationCompleted to disable the activity indicator.

Frow what I can tell, OnNavigationStarted fires and some time later OnNavigationCompleted / OnContentLoaded both fire. But then it seems other items on the web page that are subsequently loaded seem to be triggering OnNavigationStarted again, with no subsequent OnNavigationCompleted event. Some of these seem to be "about:blank" URLs, others look to be JS code such as Google Analytics, banner ads, and iFrames, all likely asyncronous loading.

The resulting behavior is that the loading indicator turns on and never turns off. When starting from an input URL, I have something to compare to (e.g. the domains). However, in dealing with link clicks, http redirects, etc the only place I can determine the URL is in the OnNavigationStarted event.

I've been looking at different variables, such as (bool) Navigating to see if there's a way of determining if it's an actual navigation or just content loading on the same page, but I can't seem to make any headway. I'm not sure if this is a bug, or if something is wrong with my code. Any recommendations?

Thanks,
David

`

private void OnNavigationStarted(object sender, DecisionHandlerDelegate e)
{
    Loading.IsVisible = true;
    Loading.IsRunning = true;
    Loading.IsEnabled = true;

    BackButton.IsEnabled = (webView.CanGoBack) ? true : false;
    BackButton.Opacity = (webView.CanGoBack) ? 1 : 0.5;
    ForwardButton.IsEnabled = (webView.CanGoForward) ? true : false;
    ForwardButton.Opacity = (webView.CanGoForward) ? 1 : 0.5;

    //e.Cancel = ViewModel.IsCancelled;
}

private void OnNavigationCompleted(object sender, string url)
{
    Loading.IsVisible = false;
    Loading.IsRunning = false;
    Loading.IsEnabled = false;

    BackButton.IsEnabled = (webView.CanGoBack) ? true : false;
    BackButton.Opacity = (webView.CanGoBack) ? 1 : 0.5;
    ForwardButton.IsEnabled = (webView.CanGoForward) ? true : false;
    ForwardButton.Opacity = (webView.CanGoForward) ? 1 : 0.5;

    scrollView.ScrollToAsync(0, 0, false);
}

`

@dczaretsky
Copy link
Author

dczaretsky commented Sep 21, 2019

Looking into this further, I realized that any content loaded on the page (ads, iframes, js, etc) would trigger the onNavigationStarted function, which made the event unusable in my case.

Instead I used a hack to inject JS into the page after the content loads to trigger an event just before navigating away from the page (beforeunload & unload events). It seems to work really well in most cases where the web page allows for it.

Perhaps a new event like onPageNavigationStarted could be added.

In my constructor, I had to declare the local/global callback functions:
`

        webView.EnableGlobalCallbacks = true;
        webView.AddLocalCallback("pageNavigation", OnPageNavigation);
        FormsWebView.AddGlobalCallback("pageNavigation", OnPageNavigation);

`

Here is my code. Hoping this could be useful for anyone stuck on the same problem.

`

    void OnPageNavigation(string obj)
    {
        Device.BeginInvokeOnMainThread(() =>
        {
            //System.Diagnostics.Debug.WriteLine($"Got callback: {obj}");
            Loading.IsVisible = true;
            Loading.IsRunning = true;
            Loading.IsEnabled = true;
        });
    }

    private async void OnContentLoaded(object sender, EventArgs e)
    {
        if (sender == null || !(sender is FormsWebView))
        {
            return;
        }

        FormsWebView _webview = sender as FormsWebView;

        // inject beforeunload & unload events to trigger pageNavigation() function
        string js_script = "window.addEventListener('beforeunload', function() { try { pageNavigation(window.location.href); } catch(e) {} }); " +
                           "window.addEventListener('unload', function() { try { pageNavigation(window.location.href); } catch(e) {} }); ";
        var response = await _webview.InjectJavascriptAsync(js_script);

        Device.BeginInvokeOnMainThread(() =>
        {
            Loading.IsVisible = false;
            Loading.IsRunning = false;
            Loading.IsEnabled = false;

            BackButton.IsEnabled = (webView.CanGoBack) ? true : false;
            BackButton.Opacity = (webView.CanGoBack) ? 1 : 0.5;
            ForwardButton.IsEnabled = (webView.CanGoForward) ? true : false;
            ForwardButton.Opacity = (webView.CanGoForward) ? 1 : 0.5;
        });

        await scrollView.ScrollToAsync(0, 0, false);
    }

`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant