Opera: Detecting back, forward, refresh and close events - javascript

I'm currently working on a jQuery plugin that tracks a visitors mouse behavior. Movements, clicks, scrolling and resizing are all recorded and sent, via Ajax, to a location where this data is parsed and stored.
Originally, the data is sent to a script when the user leaves the page. By 'leaves' I'm referring to refreshing, going back and forth though history, closing the window/tab and going to a different address.
The solution works in all browsers EXCEPT for Opera. I'm using jQuery's 'unload' event which isn't supported by Opera at all. Neither is onbeforeunload or onunload.
The question is, how do I implement this kind of functionality for Opera browsers?
One solution I had was to make special use of a 'polling' feature I created. This feature allows you to specify an interval which pushes the content to the server every 'x' seconds. Setting this to 1 second specifically for Opera browsers would probably solve this issue, but it's an awful amount of overhead and the requests aren't always completed in sequence, etc ...
Any suggestions or am I only stuck with the above option?
Thanks!
I suppose I could just link you guys to the plugin source. http://www.thedrunkenepic.com/junk/jquery.mousalytics.js
Regarding the code linked above, adding:
if(window.opera)
{
options.interval = 1;
}
On line 89 works great. My only concern is overhead, so I'm still looking for a more elegant solution.

According to http://bytes.com/topic/javascript/insights/799229-browser-quirk-onload-onunload-do-not-fire-back-forward-refresh-opera, Opera never really fires onload / onunload events, so functionality like this isn't possible without hacks.
http://dev.opera.com/articles/view/efficient-javascript/?page=4 seems to confirm this, and basically states that opera tries to maintain the state of the page across requests.
On further investgation, http://unitehowto.com/Onunload indicates that it might be possible with opera.io.webserver.addEventListener('_close', onunload, false); (where onunload is a previously defined function), however it also indicates that this functionality is not consistent across all versions of opera, and might not work at all.
I think that your best option is probably to use the polling option for Opera, or possibly use a server-side check for the current page and where it falls in the history queue.

Does adding this line of JavaScript work for you?
history.navigationMode = 'compatible';
Source: http://www.opera.com/support/kb/view/827/

I've had the same problem and this saved my day:
if( typeof(opera) != 'undefined' )
{
opera.setOverrideHistoryNavigationMode( 'compatible' );
history.navigationMode = 'compatible';
}
More info about this problem can be found at: http://www.opera.com/support/kb/view/827/

Related

Detect if beforeinput is supported

I made use of the https://github.com/jaridmargolin/formatter.js library in my project and discovered it is not working properly on mobile devices.
My research showed that this is due to it's use of keypress which is evil and should not be used. So I decided to modify it and use "beforeinput" whenever available. And here lies the problem, how do I detect whether it is available?
I tried this methode: https://stackoverflow.com/a/2877424/13987708
But it doesn't work.
My Internet search only showed me a bunch of different veriations of the same methode when checking for detecting supported events in a browser. And I can see that this method most of the times works. it even works for the "input" event, but unfortunatly not for the "beforeinput" event.
I would love to find a way that does not rely on the user agent, as that is, so I'm told, very unrelyable.
// EDIT
Well, I did research the issue, I even say so in my question :duh:...
The situation is that "keypress" is deprecated and should not be used anymore, in fact in Chrome for Android it doesn't even fire anymore.
The above mentioned plugin to format user input relies on the methode, though.
So I went ahead and replaced it with the "keyup" methode, which indeed fires in Chrome for Android, but only gives a keyCode of 229, so it doesn't work either.
I dug a bit deeper into this whole keyboard events and found that modern browsers support the "beforeinput" event (https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/beforeinput_event).
Which is awesome, it gives you so much mor information about the interaction between the user and your input.
So I adapted the formatter to use the "beforeinput" event instead of "keypress", but my project has to support IE, which does not support "beforeinput".
That's why I need a way to detect if the browser supports this event, and use either the "keypress" or the "beforeinput" depending on the capabilities of the users browser.
And I am aware that a browser might support functionality which the user won't use, but it's not relevant for this use case, I just need to know if the browser will fire the "beforeinput" event or not.

Why doesnt firefox redirect after printing?

First of all, this is a new problem which happens since a few weeks. Currently I'm using FF Version 37.
On multiple sites of our Intranet we use links, that look like this
<a href='some_page.php' onclick='window.print()'>Print</a>
The printing part works fine and normally after the printing is done, the page changes its location. This doesn't happen anymore. We found a temporary workaround, that redirects the page via JavaScript after a timeout of a few seconds. It is hard to find a timeout, that isn't too long for a good user experience and isn't too short so that the redirect doesn't fire.
Does anyone know a solution for this, except rolling back to an older version of Firefox or changing the browser entirely?
This might help
<a href='some_page.php' onclick='doPrint(); return false;'>Print</a>
function doPrint() {
window.print();
document.location.href = "some_page.php";
}
It sounds like a bug if it was redirecting for you before, I'd suggest logging a ticket with Firefox with examples

What does netflix use to detect if the user is AFK?

Though the title is decently explanatory, I'm curious as how netflix detects how a user is afk. I've looked through the code via chrome's inspect element, and found it may be done through javascript/jquery depending on the mouse position. Is there anyway anyone can verify this or if incorrect, discover the method it is determined? I'm looking to make a plugin to prevent it from pausing.
It's hard to know for sure what Netflix exactly uses to determine if a user has left Netflix, as Netflix probably obfuscates their JavaScript code and it's illegal to reverse engineer it. But there a few possibilities:
A timer that constantly calls document.hasFocus() to see if it has changed.
Most web browsers (Firefox v10+, Chrome v13+, Internet Explorer v10+, Opera v12.10+, and Safari v7+) have a built-in event to check if a window/tab is active or not. Mozilla has documentation on using the visibilitychange event, including an example with a video that pauses or plays when the visibility changes.
Whenever the javascript events onmousemove or onkeydown is called and the page is loaded for the first time, a variable is set to the current unix time. A timer checks this variable to see if so much time has elapsed since the event is called to see if the user has left the window. This is highly unlikely as people may watch a 2 hour movie without ever touching their mouse or keyboard.
There's also this previous question on StackOverflow which includes many different answers to the same question you asked.

Bug with Chrome's localStorage implementation?

Further to this question, I'm getting a curious result when binding a function to the change event of the Storage object in Chrome 8.0.552.224.
The test:
<!DOCTYPE html>
<html>
<head>
<title>Chrome localStorage Test</title>
<script type="text/javascript" >
var handle_storage = function () {
alert('storage event');
};
window.addEventListener("storage", handle_storage, false);
</script>
</head>
<body>
<button id="add" onclick="localStorage.setItem('a','test')">Add</button>
<button id="clear" onclick="localStorage.clear()">Clear</button>
</body>
</html>
Open up the page in two Chrome windows, one window with two tabs,
Click the 'Add' button
When I do this I get an alert box displayed on on the second tab and on the second window but not on the tab that invoked the event (the I clicked on). As I understand it I should see three alert boxes (one for each tab opened).
Is this a bug? Is anyone else getting this behaviour? If not what version are you running? Or have I just got this all completely wrong?
Update and final conlusion
It turns out that the spec actually says that this is the desired behavior, therefore IE9's implementation is broken.
4.2 The sessionStorage attribute
When the setItem(), removeItem(), and clear() methods are called on a Storage object x ... if the methods did something, then in every HTMLDocument ... [that is] associated with the same storage area, other than x, a storage event must be fired....
So as we can see, the spec does do a really bad job at making it clear, that this is the specified behavior. That was the reason why Opera 10's implementation was broken and it's most likely also the reason why IE9's implementation is broken.
What do we learn from that? Always read every, single, word of the specification (especially if you're implementing the stuff...).
Old answer
As you said the basic behavior here is "Invoke on all but the current page".
There's an old Chrome Bug Report from last July.
As one can read there, Firefox has the same "issue". I've tested this with the latest nightly, still behaves the same way like in Chrome.
Another test in Opera 11 shows that this must be some kind spec'ed behavior, since Opera 11 does the exact same thing but Opera 10 did fire events on all windows / tabs. Sadly the official changelogs for Opera 11 do not state any change for this behavior.
Reading through the specification, nothing there states this behavior. The only thing I could find is:
The storage event is fired when a storage area changes, as described in the previous two sections (for session storage, for local storage).
When this happens, the user agent must queue a task to fire an event with the name storage, which does not bubble and is not cancelable, and which uses the StorageEvent interface, at each Window object whose Document object has a Storage object that is affected.
Note: This includes Document objects that are not fully active, but events fired on those are ignored by the event loop until the Document becomes fully active again.
Well, what does the Note mean?
From another specification:
A Document is said to be fully active when it is the active document of its browsing context, and either its browsing context is a top-level browsing context, or the Document through which that browsing context is nested is itself fully active.
Doesn't make sense? Yes. Does it help us in any way? No.
So we (in the JavaScript Chatroom) poked on #whatwg to see what all of this is about, so far there has been no response. I'll update my answer as soon as we get any response.
To conclude for now
Firefox, Chrome, Safari and Opera have the exact same behavior. That is, they do not fire on the tab / window that made the chance to localStorage.
But IE9 Beta behaves like Opera 10, so it fires on all tabs / windows.
Since the author of the localStorage spec works at Google in R&D, I hardly doubt Chrome would get this wrong. And since there are no Bugs on this over at Bugzilla and Opera changed the behavior in 11, it seems that this is the way it should work. Still no answer why it works this way and why IE9 behaves differently, but we're still waiting for a response from #whatwg.
Ivo Wetzel's answer for what is going wrong is correct.
I was having the same problem but managed to work around this limitation in the spec by manually creating and firing a StorageEvent in the tab that initiated the storage change (see StorageEvent#initStorageEvent).

Why won't Internet Explorer (or Chrome) display my 'Loading...' gif but Firefox will?

I have a page that fires several xmlHttp requests (synchronous, plain-vanilla javascript, I'd love to be using jquery thanks for mentioning that).
I'm hiding/showing a div with a loading image based on starting/stopping the related javascript functions (at times I have a series of 3 xmlhttp request spawning functions nested).
div = document.getElementById("loadingdiv");
if(div) {
if(stillLoading) {
div.style.visibility='visible';
div.style.display='';
} else {
div.style.visibility='hidden';
div.style.display='none';
}
}
In Firefox this seems to work fine. The div displays and shows the gif for the required processing. In IE/Chrome however I get no such feedback. I am only able to prove that the div/image will even display by putting alert() methods in place with I call the above code, this stops the process and seems to give the browsers in question the window they need to render the dom change.
I want IE/Chrome to work like it works in Firefox. What gives?
if the xmlhttprequests are not asynchronous you will find IE at least wont rewrite the UI untill they are finished (not tested in Chome though), I cam across the same issue with non async $.ajax jquery requests.
I realize you're not asking about jQuery but you might consider using jQuery to show/hide your div for easier cross browser compatibility.
http://api.jquery.com/show/
http://api.jquery.com/hide/
Here's a helpful tutorial:
http://www.learningjquery.com/2006/09/slicker-show-and-hide

Categories