Is there a way to prevent MobileSafari from continuing on the path of navigating to a new URL whenever I am debugging a complex interaction that involves an anchor tag with a valid HREF attribute?
I'm developing some Javascript code and testing click/touch events on an iPad. I've got Safari's Dev Tools on my Mac communicating with Mobile Safari on iPad with no issue. My issue looks like the following:
On the iPad, I click an tag that can do some complex interactions (tap vs. long-press, etc).
Safari's dev tools break at my breakpoint, directly inside the event handler
The iPad continues to follow the link even though the javascript code is broken.
For example:
$('a').on('click', function(e) {
console.log('wtf');
// ...Handler Code...
});
Setting a breakpoint in Safari Dev Tools on the console.log() statement will break the Javascript as expected, but the browser will continue to navigate to the link's address, causing the page to change. This effectively keeps me from debugging any interactions involving a link click.
However, if you preventDefault() on the event, Safari will not continue (which is what would happen if I wasn't debugging):
$('a').on('click', function(e) {
e.preventDefault();
console.log('wtf');
// ...Handler Code...
});
This is very different from how Chrome/Firefox/IE handle this style of debugging. Is this a bug in MobileSafari or Safari Dev Tools, or am I missing something?
Related
I've been going somewhat crazy trying to debug a file drag and drop issue in an application I'm working on. What's happening is that Chrome is firing onDragEnter, OnDragOver and onDrop events (the only events I'm using) outside the element on which they're defined but only when devtools is open. I can't share my code but I can reproduce the issue easily using this bare bones example on JSBin: https://jsbin.com/hiqasek/edit?html,js,output
With devtools open, if I drag a file from Finder up toward the target div the onDragEnter event happens when the cursor is about 75 or 100 pixels below the div. If I go ahead and drop the file there the onDrop event fires. The end result is as expected but from the wrong cursor position. Now if I close devtools and do this again, the events fire "pixel perfect" inside the div.
Running in incognito mode with extensions disabled yields the same result.
My setup: MacOS 10.15.7 with Chrome 95.0.4638.69. This did not happen when testing with Edge 95.0.1020.40 and Safari 15 v15612.1.29.41.4.
EDIT: Does not happen in the same version of Chrome on Windows 10 20H2 (19042.1288)
Am I overlooking something (very possible), or is this is a bug in Chrome?
I have a web application in which I have a div element with an onclick javascript action. This web application works fine on iPads and desktops alike.
When it is launched within an iFrame on an iPad, however, all of the sudden, my clicks/taps are rarely and inconsistently acted upon. When running in an iFrame on a desktop browser, I do not see this behavior.
Has anyone seen this type of behavior before?
I'm not sure about your exact situation, but I was having a similar problem when my botton had a "mouseenter" event trigger binded to it. The mouse enter would be called on the first "tap" and the button would be called on the "second". Because of the way ipad uses those two events.
My solution was to use the browser detection tool from http://detectmobilebrowsers.com/ and set a var ismolible = to true or false, depending on whether the browser was mobile or not, then I used an if statement to unbind my mouseenter immediately if the browser was mobile. You do have to modify the http://detectmobilebrowsers.com/ code for ipad.
Hope this helps!
I have a web application in which I have hooked mouse up and mouse down events; I use them for selection and manipulation of the graphical language for which my application is an editor. To prevent the right-click/context menu supplied by Firefox from showing up, I've placed:
if (evt.preventDefault) {
evt.preventDefault();
}
at the top of each of my mouse up and mouse down event handlers. I don't want to return false; I actually want the event to propagate.
On the Mac, the right-click menu doesn't show up; this is what I expect. On Windows, however, it stubbornly appears, even though Firebug confirms that my call to "preventDefault" is occurring and likewise "defaultPrevented" gets set to true.
Any idea what gives? Has anyone else run across this problem? I'm running Firefox 6.0.2 on both the Mac and Windows.
[Update: more recent versions of Firefox yielded consistent results on Mac and Windows: the context menu failed to be suppressed on both platforms.]
Okay. After putting this aside and returning to it several times, I finally found the solution.
Attempting to deal with the appearance of the context menu in the various mouse listeners appears to be fundamentally flawed. Instead, thanks to code I found here, I was put on the scent of the contextmenu event. That event appears to be the right way to handle things, although the code actually posted on that site didn't do the trick — merely calling "stopPropagation" and returning false was insufficient.
The following worked for me:
element.addEventListener('contextmenu', function(evt) {
evt.preventDefault();
}, false);
This has been tested with Firefox 10.0 on a Mac and Firefox 9.0.1 and 10.0 on Windows 7.
This option is removed in Mozilla's 23rd version.
Go to Tools > Options.
Go to the Content tab.
Click Advanced button next to Enable JavaScript option.
Disable or replace context menus. Check this box and it will magically work again.
There is no way to get around this setting in JavaScript.
I have this HTML.<html><body>
PLAY ME!!!!!
</body></html> So if somebody clicks on the link then native media player loads and browser goes into background and when video ends it comes to foreground with the same page. Is there a way to detect this i.e. browser going background and then coming foreground in the javascript?
Android Chrome has the visibilitychange event; example code is here: http://output.jsbin.com/rinece
To test:
on Android Chrome open that link
Either
watch the log below the clear button and notice the delay times (so you can see exactly when the event occurred within the page).
or attach the debugger and watch the console
or if you can't attach the debugger (WebView or AOSP) then open http://output.jsbin.com/rinece#http://localhost:80/ and use a proxy or set up a localhost server that shows you the body content (the log text is in the body of the xmlhttp requests; change the # url to a proxy or server where so you can see the Requests occur).
Change tabs
Watch the log to confirm which events occur on visibilitychange
AOSP (and WebView for Android < 4.4) may have different behaviour than Chrome...
The visibilityChange event is now well supported on mobile - see http://caniuse.com/#search=visibility but beware that it is not supported by iOS UIWebView (even if on iOS9).
So as the article that #ndtreviv linked says that "Switching to another document or application." is not implemented in Android yet. However, you can, if you want to, make an app that uses a WebView to display your content. This way, you can access all the native Android stuff from JavaScript.
There is a proposal to allow mobile webapps to detect whether they are in the foreground or not, you can use the "visibilitychange" event, see here: http://www.w3.org/TR/2013/REC-page-visibility-20131029/#sec-visibilitychange-event
Note that this event is fired on the document, not on the window. E.g:
window.document.addEventListener("visibilitychange", function(e) {
window.console.log('VISIBILITY CHANGE', window.document.visibilityState);
});
Does anyone know if the onbeforeunload event is supported on the iPad and/or if there's a different way to use it?
I've tried pretty much everything, and it seems like the onbeforeunload event is never triggered on the iPad (Safari browser).
Specifically, this is what I've tried:
window.onbeforeunload = function(event) { event.returnValue = 'test'; }
window.onbeforeunload = function(event) { return 'test'; }
(both of the above together)
window.onbeforeunload = function(event) { alert('test')'; }
(all of the above functions but inside <body onbeforeunload="...">
All of these work on FF and Safari on the PC, but not on the iPad.
Also, I've done the following just after loading the page:
alert('onbeforeunload' in window);
alert(typeof window.onbeforeunload);
alert(window.onbeforeunload);
Respectively, the results are:
true
object
null
So, the browser does have the property, but for some reason it doesn't get fired.
The ways I try to navigate away from the page are by clicking the back and forward buttons, by doing a google search in the top bar, by changing location in the address bar, and by clicking on a bookmark.
Does anyone have any idea about what's going on? I'd greatly appreciate any input.
Thanks
This bit of JavaScript works for me on Safari and Chrome on ipad and iphone, as well as desktop/laptop/other browsers:
var isOnIOS = navigator.userAgent.match(/iPad/i)|| navigator.userAgent.match(/iPhone/i);
var eventName = isOnIOS ? "pagehide" : "beforeunload";
window.addEventListener(eventName, function (event) {
window.event.cancelBubble = true; // Don't know if this works on iOS but it might!
...
} );
I have found that the onunload() event does fire. It's behavior is somewhat odd; whatever you have in your callback function attached to the event is actually run after the new page has loaded in the background (You can't tell it's loaded yet, but server logging will show that it has).
More oddly, if you have a confirm() call in your onunload(), and the user has clicked a link to go somewhere else, you are in business. If, however, the user closes the iPad Safari browser tab, the onunload() event will fire, but your confirm() will have an implicit cancel as response.
Only Apple would know for sure, but my guess is that they purposely did not enable that functionality in mobile Safari because it is most often used by shady characters to get you to stay on their site or pop up lots of porn/advertising windows.
There's a known bug in WebKit with onbeforeunload. I believe it's fixed in the latest beta of Chrome 5, but it's quite possible the iPad's browser is made from a version of WebKit that doesn't have the fix.
Related Chrome bug report.
beforeunload event is not supported by Mobile Safari. You can see the list of all supported events here: Handling Events Apple documentation
And the beforeunload is not in the list!
https://code.google.com/p/chromium/issues/detail?id=97035
see hear.
alerts are no longer allowed during page dismissal events (beforeunload, unload, pagehide).
I think alerts, prompt, confirm, and other actions like these are also no longer allowed.
Here's a solution that should work on all modern browsers:
var unloaded = false;
window.addEventListener("beforeunload", function(e)
{
if (unloaded)
return;
unloaded = true;
console.log("beforeUnload");
});
window.addEventListener("visibilitychange", function(e)
{
if (document.visibilityState == 'hidden')
{
if (unloaded)
return;
unloaded = true;
console.log("beforeUnload");
}
});
Mobile browsers don't tend to not support beforeunload because the browser can go into the background without unloading the page, then be killed by the operating system at any time.
Most desktop browser contain a bug that causes visibilityState to not get called when the document unloads. See: here.
Therefore, it's important to include both events to cover all scenarios.
NB
I have used console.log instead of alert in my example because alert will get blocked by some browsers when called from beforeunload or visibilitychange.
If you just need to know if the page has been left you can use document.unload. It works fine in ios browsers. If you see on Apple documentation you'll find that it's deprecated and they recommend to use document.pagehide