iPhone/iTouch not firing (new Image) request onunload - javascript

Hey guys, hope someone can help me out.
I'm making a small application to record clicks, which is going great, until I hit the iPhone/iTouch. I'd like to point out, that I've been testing with an iTouch, and I am just presuming the same thing will happen on a iPhone.
What I have at the moment is something similar to this,
<script>
function save(){
// Capture link, with var mycoords containing string
var a = 'http://mydomain.com/capture.php?co='+mycoords;
var img = new Image(1,1);
// Loads link with params, PHP uses $_GET
img.src = a;
alert('f'); // For testing
}
// alerts 'f', does not send data on device
window.onunload = save;
// alerts 'f', does not send data on device
window.onunload = (function(){
save();
});
// Alerts 'f', does not send data on device
window.addEventListener("unload",save,false);
</script>
This code works on all my desktop browsers, including Safari, but on the iTouch/iPhone, no. If I execute the save() function outside any onunload practice, the data sends just fine. I know the onunload works, due to the alerts. But I am absolutely baffled by image object not working in this instance, yet working everywhere else. I have had a good look about on the net, and have found no solution.
Perhaps someone here can maybe give me a solution or an explanation to why this is happening? I would be very grateful. Thank you for your time.

Basically there is no way to detect onunload reliably, as is answered here: javascript unload event in safari mobile?
If you're trying to track clicks, I would suggest adding a click event handler to the link which would first call your save() function and then it could return true or update the document.location.href to take the user to the final link.

Related

javascript window.location issue with IE and Firefox

I have some strange behavior on my window.location redirects in IE and Firefox as part of my angular application. When calling window.location = xyz the first time it works fine in IE/FF/Chrome. On the second call which is supposed to go to google.com, Chrome does what it's supposed to, but IE and FF don't do anything. In the IE web console I can see that the navigation was triggered but the page and URL hasn't changed in my window. Now if I press F5 on this page it goes to the page it's supposed to even though the URL at the top is not pointing there (both in IE and FF).
Has anyone ever encountered this problem and knows how to solve it? I've tried all versions of redirecting (window.location, window.location.href, windows.location.assign(), window.location.replace() and also the angular service $window) with no luck.
First call triggered from a button press (working fine in all browsers):
$scope.pressButton = function() {
var url = 'xyz/index.html';
$window.location = url;
};
Second call triggered by a keypress (only works in Chrome):
function exitModule() {
$window.location = 'http://www.google.com';
console.log('window.location'); // still pointing to the old page
}
Update with code calling the exitModule() function:
Note: The application is built with angularjs.
The exitModule() function gets called in all browsers, it's just the redirect which doesn't happen in IE/FF.
HTML:
<body ng-app="myModule" ng-controller="MainCtrl" ng-keydown="keyPress($event);">
JS:
// Handle global key press
$scope.keyPress = function(event){
if(event.which === 27) { // EscapeKey
exitModule();
} else {
$scope.$broadcast('keyPress', event);
}
};
Alright I found the issue and I'm aware that it was almost impossible to figure this out without having the full code available. The above code was a bit simplified therefore it was missing the problem. The function exitModule gets called as soon as a promise is resolved. The call looks like this:
Correct
dataService.saveModule().then(exitModule);
My code was as shown below with the brackets after exitModule which is wrong. I don't quite understand the behavior of FF/IE compared to Chrome though ...but that's for another day.
Wrong
dataService.saveModule().then(exitModule());

Will javascript loop make my page get eventually stuck?

i have this function:
<script language="javascript">
function live(){
var d = $live;
var elm = document.getElementById("live");
if(d==1){
elm.style.display = 'block';
} else{
elm.style.display = 'none';
}
}
</script>
setInterval(function(){live();},10000);
and im just concerned about my page getting stuck after having it open on the browser for a while or causing my users browser to stop responding or anything like that. How safe is to use loops like this?
Is this what google or facebook use to show new notifications alerts on their page in real time? That seems to go pretty smoothly.
Thank you.
This isn't a loop in the traditional sense, it's really just a function which is called at a regular interval, so you are in the clear here. Just be careful that nothing increases the memory use each time it executes, as that is what will most likely be what will kill the user's browser.
Also, the setInterval needs to me in a script tag, otherwise it will show up on your page.
Use of setInterval is a common practice for showing notifications on websites. It wont hang your page, although you must clear the interval once it is no longer required. Say you have already shown the notification, so better hold the reference of setInterval so that you could clear it later.
var ref = setInterval(fn, 100);
clearInterval(ref);

Phonegap App Error - connection to the server was unsuccessful

I have the following issue and I'm a bit new to Phonegap! On my index page I have three functions that will create a Javascript Prompt asking the user for their name, email and title (position) and store each to the localStorage. Three items like this:
function promptName(){
var salesPName = prompt("Bitte geben Sie Ihren Namen","");
if(salesPName == null || salesPName == ""){
promptName()
}else{
localStorage.setItem("salesP", salesPName);
}
}
Then using $(document).ready I call these three functions:
$(document).ready(function(){
if(!localStorage.getItem("salesP")){
promptName();
promptEmail();
promptPosition();
}
});
This is all working well, however when deploying to my Android device I get the prompts but before I can complete all three I get an error dialog stating:
The connection to the server was unsuccessful (file:///android_asset/www/appname/index.html)
Removing the prompts removes the error but I need this functionality. I have tried different ways of calling the functions, for example on the body tag's onload event or using .load(). I still get this error. I thought about setting a Javascript interval to call this after a few seconds (once the page is loaded) as I'm sure the problem is due to Javascript's blocking nature. Has anyone come across this before?
Please note that I added the following to the com.mypackage.xxx.java file (as advised from phonegap, connection to server unsuccessful)
super.setIntegerProperty("loadUrlTimeoutValue", 10000);
And I still get the problem!
with nothing working I put a setTimeout() around my condition like so...
$(document).ready(function(){
setTimeout(function (){if(!localStorage.getItem("salesP")){
// item doesn't exist... so let's raise some dialogs to capture the name, email address and title
promptName();
promptEmail();
promptPosition();
}
}, 5000)
});
now it works fine... a bit of a fudge but so what, if anyone has any ideas on a better solution or any objections to this please let me know

window.onbeforeunload in Chrome: what is the most recent fix?

Obviously, window.onbeforeunload has encountered its fair share of problems with Chrome as I've seen from all the problems I've encountered. What's the most recent work around?
The only thing I've got even close to working is this:
window.onbeforeunload = function () { return "alert" };
However, if I substitute return "alert" with something like alert("blah"), I get nothing from Chrome.
I saw in this question that Google purposefully blocks this. Good for them... but what if I want to make an AJAX call when someone closes the window? In my case, I want to know when someone has left the chatroom on my website, signalled by the window closing.
I want to know if there's a way to either
(a): fix the window.onbeforeunload call so that I can put AJAX in there
or
(b): get some other way of determining that a window has closed in Chrome
Answer:
$(window).on('beforeunload', function() {
var x =logout();
return x;
});
function logout(){
jQuery.ajax({
});
return 1+3;
}
A little mix and match, but it worked for me. The 1+3 makes sure that the logout function is being called (you'll see 4 if it's successful on the popup when you try to leave).
As of Chrome 98.0.4758.109 and Edge 100.0.1185.29, Chromium has not met the standard. There is a bug report filed, but the review is abandoned.
Test with StackBlitz!
Chrome requires returnValue to be a non-null value whether set as the return value from the handler or by reference on the event object.
The standard states that prompting can be controlled by canceling the event or setting the return value to a non-null value.
The standard states that authors should use Event.preventDefault() instead of returnValue.
The standard states that the message shown to the user is not customizable.
window.addEventListener('beforeunload', function (e) {
// Cancel the event as stated by the standard.
e.preventDefault();
// Chrome requires returnValue to be set.
e.returnValue = '';
});
window.location = 'about:blank';
Here's a more straightforward approach.
$(window).on('beforeunload', function() {
return "You should keep this page open.";
});
The returned message can be anything you want, including the empty string if you have nothing to add to the message that Chrome already shows. The result looks like this:
According to MDN,
The function should assign a string value to the returnValue property
of the Event object and return the same string.
This is the following
window.addEventListener( 'beforeunload', function(ev) {
return ev.returnValue = 'My reason';
})
This solved my problem why it wasn't working in my app:
Note that the user must interact with the page somehow (clicking somewhere) before closing its window, otherwise beforeunload is ignored in order not prevent abuse.

Chrome JavaScript location object

I am trying to start 3 applications from a browser by use of custom protocol names associated with these applications. This might look familiar to other threads started on stackoverflow, I believe that they do not help in resolving this issue so please dont close this thread just yet, it needs a different approach than those suggested in other threads.
example:
ts3server://a.b.c?property1=value1&property2=value2
...
...
to start these applications I would do
location.href = ts3server://a.b.c?property1=value1&property2=value2
location.href = ...
location.href = ...
which would work in FF but not in Chrome
I figured that it might by optimizing the number of writes when there will be effectively only the last change present.
So i did this:
function a ()
{
var apps = ['ts3server://...', 'anotherapp://...', '...'];
b(apps);
}
function b (apps)
{
if (apps.length == 0) return;
location.href = apps[0]; alert(apps[0]);
setTimeout(function (rest) {return function () {b(rest);};} (apps.slice(1)), 1);
}
But it didn't solve my problem (actually only the first location.href assignment is taken into account and even though the other calls happen long enough after the first one (thanks to changing the timeout delay to lets say 10000) the applications do not get started (the alerts are displayed).
If I try accessing each of the URIs separately the apps get started (first I call location.href = uri1 by clicking on one button, then I call location.href = uri2 by clicking again on another button).
Replacing:
location.href = ...
with:
var form = document.createElement('form');
form.action = ...
document.body.appendChild(form);
form.submit();
does not help either, nor does:
var frame = document.createElement('iframe');
frame.src = ...
document.body.appendChild(frame);
Is it possible to do what I am trying to do? How would it be done?
EDIT:
a reworded summary
i want to start MULTIPLE applications after one click on a link or a button like element. I want to achieve that with starting applications associated to custom protocols ... i would hold a list of links (in each link there is one protocol used) and i would try to do "location.src = link" for all items of the list. Which when used with 'for' does optimize to assigning only once (the last value) so i make the function something like recursive function with delay (which eliminates the optimization and really forces 3 distinct calls of location.src = list[head] when the list gets sliced before each call so that all the links are taken into account and they are assigned to the location.src. This all works just fine in Mozilla Firefox, but in google, after the first assignment the rest of the assignments lose effect (they are probably performed but dont trigger the associated application launch))
Are you having trouble looping through the elements? if so try the for..in statement here
Or are you having trouble navigating? if so try window.location.assign(new_location);
[edit]
You can also use window.location = "...";
[edit]
Ok so I did some work, and here is what I got. in the example I open a random ace of spades link. which is a custom protocol. click here and then click on the "click me". The comments show where the JSFiddle debugger found errors.

Categories

Resources