Display loading indicator when navigating away from page on Safari - javascript

I would like to display a nice page transition when navigating between pages on a site.
I've tried using these events: beforeunload unload pagehide and also visibilitychange.
There was a webkit bug described as
visibilitychange:hidden doesn't fire during page navigations
And a workaround is listed:
using the pagehide event is the workaround
I am adding a class to the html element on these events. On Chrome and Firefox this activates my loading indicator class and the animation is displayed until the page is replaced. I get a nice loading transition between page navigation. So, in Chrome and Firefox, everything works great.
Unfortunately, I am not having any luck with Safari on iOS (iPhone or iPad) and also failing on macOS Big Sur Safari. I found a related question here: Safari change dom on before unload page however, it only discusses the beforeunload event. I am hoping that by being less specific here that a viable alternative pops up.
I have tested the css works on Safari by manually applying it and also verified my listeners are called on Safari via the javascript console. However the css change doesn't seem to be rendered. There is no transition shown on the page being unloaded before getting the new page response from the server. I've also verified it isn't related to the CSS in use by setting a simple background color without any transition or similar effects.
So far, the only way that I have been able to get Safari to render the dom change is by returning a truthy string on unload - but this prompts the user if they want to leave or not which is not my intention.
I want to avoid browser detection - however the last viable alternative I can come up with is scanning the dom for anchors, buttons, forms, etc when Safari is detected to enable the loading indicator before navigating.
Are there any other options to consider?

Related

CSS keyframe animation not triggering when using back button on iOS device

I am running a keyframe animation on the body element of my page that fades in and out the opacity of the background. The fade in animation is run directly on the body as a CSS rule, and the fade out is triggered by setting a class to the body element, when special links a clicked. The implementation works great on Android Chrome browser, and desktop Safari, Chrome, Firefox, IE11 and Edge.
The fadeout animation also works great when I click a link from an iOS device, but once I use the native back button in Safari it seems that the page just goes back to a previous view that it saved of the last page, without running the fadein animation again. Therefore the page looks broken.
How can I handle this? can I somehow force the iOS device to reload the page when I navigate back? or Would there be another way to handle it?
Safari does not "reload" the page when you hit the back button. One common workaround is to add some code to the footer of the page to tap into the pageshow event. You could then do something like.
const reloadAnimation = () => $("#my-element").removeClass("run-animation").addClass("run-animation");
window.addEventListener('pageshow', reloadAnimation)

IE9 Window Loses Focus due to jQuery Mobile

In our product, we're using the most recent development version of jQuery Mobile in our ASP.NET website. Each and every time we do an ASP.NET postback, the browser window goes to the back of the screen.
Example:
Maximize any window. Example: Visual
Studio, Word, Windows Explorer.
Maximize IE9 over it. IE9 is the only
thing you see on the screen.
Click on a button in our solution that does
a postback.
IE9 is no longer visible.
Whatever was behind it now has focus
(and fills the screen, as it is
maximized)
Only workarounds I know:
Don't include the jQuery mobile scripts.
Ensure IE9 is the only maximized window in Windows.
I don't know what jQuery Mobile is doing in the background and am assuming this is a bug in IE9 that will eventually be fixed. However, if you had any tips on how to prevent it from happening in the meantime, that would be great.
Edit: Seems it isn't on every postback. It is on every postback that performs a Response.Redirect. I should add that all my postback are actually utilizing ASP.NET AJAX, not full postbacks.
I know this is an old post, but for people coming here from Google:
I ran into this same issue today. It seems this lose focus behavior is what IE does when you trigger the blur event on the window object. This was the code that caused this issue for me:
$(document.activeElement).blur();
activeElement will default to the body element when there are no other elements in focus, and the blur event then bubbles up to the window. To fix this I simply did a check like:
if (document.activeElement != $('body')[0]) {
$(document.activeElement).blur();
}
I had similar problem with IE10 and jQuery 1.7.2.
I found these lines in my code:
$(document.activeElement).blur();
and
$(':focus').blur();
So, adding simple .not('body') resolves the problem:
$(document.activeElement).not('body').blur();
$(':focus').not('body').blur();
This same issue seems to occur with jQuery Mobile 1.4.2.
When using IE 10, with a single tab open and another window on the same monitor, if you open a popup it will send the browser to the background.
To fix this you have to edit the _handleDocumentFocusIn function. You need to change the line(10391) that reads:
target.blur();
to
if (targetElement.nodeName.toLowerCase() !== "body")
{
target.blur();
}
I made a pull request so hopefully this will be included in the next version.
Just posting this link to anybody who is experiencing more of this continued mess. I am seeing the problem on IE 9 and IE 10 on a window.location = 'BLAH', from within the Angular location resource.
This doesn't seem to solve the problem for me, but it may help others:
http://support.microsoft.com/kb/2600156/en-us

When does (mobile) Safari/Chrome consider a page loaded using Comet?

I have a website that uses a long-polling comet connection. The connection needs to be setup on/after page load.
Despite my efforts to prevent it, many browsers consider the long-poll request to be part of the page loading mechanism, thus keeping the page in a 'loading' phase. In Safari this results in the progress bar (behind the url field) to not complete. In Chrome the favicon is shown as a spinning loading icon. Even more problematic is mobile safari on iphone, that does not allow hiding the url field while 'loading'. Mobile android has similar issues on some devices.
All in all, the behavior is difficult to reproduce and seems to be dependent on browser/platform/connection speed/etc. Right now, my code initiates the long polling 10msecs after the window.onLoad trigger. This seems to work well often, but not always. I suspect it may have something to do with loading some external (image/javascript) resources, yet one would say the onLoad event is fired after these are completely loaded.
Anyone some pointers on how to force these browsers into considering my page as loaded? Ideally, one could somehow mark an xmlhttprequest as comet-like, but this is no feature :).
I've been having the same issue and found that if you allow the page to exit its onload handler before issuing your long polling ajax request, everything works fine and the page does not go back into a loading state.
So for example, what usually would be
$(document).ready(function() { $.ajax(...); });
would become
$(document).ready(function() setTimeout(function() { $.ajax(...); }, 0); });
In the particular case of WebKit, I believe that $(document).ready is a synonym for window.onload. So that's why it matters.
This worked for me on iPad1,1 with iOS 5.
We have been successful removing the "loading" indicator in Safari 5.1.5 with ajax long polling requests. Chrome unfortunately still consistently shows the loading indicator. For chrome, our team has chosen to simply change the css cursor value on the entire body element (ex: crosshair or a custom cursor) - a terrible "hack" - but at least the user won't see the loading mouse cursor while they are on the system.

window.unbeforeunload show div IE7 problem

Currently I am developing a web application for which I am using a pre-loader icon. What I want is that the pre-loader becomes visible every time the user navigates to another page or refreshes the page. So far I have the following solution:
window.onbeforeunload = function() { $("applicationdisabler").show(); };
For Safari and Firefox it works fine when the user clicks a link or refreshes the page. However in IE7 the div only becomes visible when the user clicks a link and NOT when the user refreshes the page.
The user can refresh the page by hitting F5 (on Windows) or any other possible way the browser provided.
Of course I have been looking for some workarounds already. The following code shows the alert in IE7, but the div still doesn't become visible.
window.onbeforeunload = function() { $("applicationdisabler").show(); alert("come on!"); };
The code of my div:
<div id="applicationdisabler"><img src="images/preloader.gif" /></div>
Hopefully someone can help me out.
You need to put the # before the id on the jQuery selector:
$("#applicationdisabler").show();
Why not use just use the onLoad listener instead? Although it would be slightly slower it should be more reliable.
Actually after a bit of looking around I'm not sure modifying the DOM makes any sense unless the onBeforeUnload handler returns false first - i.e. forces the user to stay on the same page.
As I understand it the onBeforeUnload event is fired just before the page is unloaded, so if you don't return false the browser will unload the page and DOM, and any JavaScript executed after that will be pointless.
That doesn't quite explain why JavaScript isn't executed properly in the onBeforeUnload function, but from what I've seen sites only use the window.alert or window.prompt dialogs to ask the user if they want to leave the site, and then often executing JavaScript if the user decides to stay.
Hence I'm guessing that some browsers may not allow DOM manipulation when this event is fired - since if the page is unloaded any DOM manipulation done is completely pointless.
So either:
Return false in your onBeforeUnload method, and then show your preloader (although this will stop navigation to the next page)
Use the onLoad event of the next page to show the preloader image instead
Also note: Opera versions 9.5 and below do not support this event (I'm unsure about later versions) but GMail does manage to catch the back button in Opera.
Possibly related is this security warning for IE7's implementation of the onBeforeUnload event - it's possible Microsoft patched it in a way that prevents the things you're trying to do. And I know IE6 and below don't allow commands like document.location='' in the onBeforeUnload handler for security reasons.

How do I focus an HTML text field on an iPhone (causing the keyboard to come up)?

I'm writing an iPhone web app, and I want to automatically focus a text field when the page is loaded, bringing up the keyboard. The usual Javascript:
input.focus();
doesn't seem to be working. Any ideas?
It will only show the keyboard if you fire focus from a click event, so put a button on the page with a onclick that does the focus and it will show the keyboard. Completely useless except for validation (on click of submit validation code focuses on invalid element)
Edit: The following no longer works on iOS - UIWebView did allow autofocus and home screen links used to autofocus but they disabled that many versions ago.
The autofocus (see below) property doesn't work from a url in Mobile Safari but does work if you are:
using a UIWebView
using a home screen link
The fontsize of the input needs to be large enough to avoid the iOS10 zoom on double-tap (now that viewport is always zoomable) and to design the page to be sized so that it fits the screen (otherwise on page loading you get strange timing/race bugs in zoom, or if scrollable the field sometimes doesn't center to the screen properly).
autofocus: The HTML5 spec for doing this is the autofocus property of the input tag. But iOS ignores that, presumably for a cleaner UI that doesn't pop up the touch keyboard when navigating to a page. Here is a page that demonstrates the autofocus property. Before HTML5 you would call element.focus() in the window.onload event. However focus() calls are not supported on iOS except during the handler of an onclick event.
Note: this answer is old and may not be relevant to newer versions out there...
It comes as no help to you but the last poster in this thread wrote that its a bug of the webkit engine.
I can't tell if its a verified bug or not...
Last post from way back machine (as original seems to not work):
I am developing my app in pure XHTML MP / Ecmascript MP / WCSS. So
using native platform browser control api is really not an option for
me. Yes the behaviour u mention is the same as mine. I searched his
topic in the bugzilla at webkit.org and found that this indeed is a
reported bug. focus() to a text box does highlight the element but
does not provide a carat in it for the user to start entering text.
Using a timer as mentioned by "peppe#peppe.net" does not help either.
This behaviour is common across platforms (s60,iphone,android) which
use the webkit engine.
So as of now i dont see a solution to this problem.
Hope this helps
I have a similar issue, only my issue is that the focus will not occur on a 'touchend' event.
http://jsfiddle.net/milosdakic/FNVm5/
The following code will work in Chrome/Safari etc. but will fail on Mobile Safari. The only way to get it to work is to make the event on 'click', but seeing as the code is made for an iOS device, it would benefit for it to work with touch events.
It seems to be a bug with the Webkit engine.
If you are setting focus with from a click event, you need to preventDefault otherwise the click events default action will set focus on the clicked item.
A bit late maybe but for future person maybe. In our webapp running on iOS iPad (6 and more recent), we do it with a set interval:
startFocusOnTextField: function() {
this.intervalIDForTextFieldFocus = window.setInterval(function() {
document.getElementById(page.textInputFieldObj.id).focus();
}, 150);
},
Which is called on page load (jQuery mobile environment)
This is a workround:
setTimeout(function(){
input.focus();
},500);//milliseconds

Categories

Resources