I'm trying to observe within my Firefox extension when a user is inactive. My current solution is derived from a similar question, found here (see accepted answer). And it basically works just fine.
I noticed, however, that it doesn't seem to distinguish between multiple open browser windows - that is, a user cannot be active in one window and inactive in another one. At the moment the active/inactive state is some global state across all Firefox windows. Thus, a user becomes really inactive, if the user is active in all open browser windows
Is there a way to distinguish between different windows, or do I have to deal with it (wouldn't be to bad, but still...)? Thanks a lot for any hints on that!
This is something that you will have to implement yourself. It also largely depends on what you mean by "inactive in a particular window". I guess that you mean the lack of mouse and keyboard activity in this window. So you would have to add a listener for keydown, keyup, mousemove, mousedown, mouseup, DOMMouseScroll, touchstart, touchend, touchmove events. The listener for these events would set a timeout, e.g. for one minute. However, it would first clear the already existing timeout if any. This way the timeout will fire one minute after the last event received, one minute after the user stopped generated keyboard or mouse events in the window.
The subject parameter the observer passes should be the window of the currently active browser window.
Related
Is there a cross browser event that can be used to show a message to the user returning to their web page?
For example, a user has ten applications or tabs open. They get a new notification from our app and I show a notification box. When they switch to our tab I want to begin our notification animation.
The activate event is common on desktop applications but so far, on the window, document and body, neither the "activate" or "DOMActivate" do anything when swapping between applications or tabs but the "focus" and "blur" do. This event works but the naming is different and the events that should be doing this are not.
So is the right event to use cross browser or is there another event?
You can test by adding this in the console or page and then swapping between applications or tabs:
window.addEventListener("focus", function(e) {console.log("focused at " + performance.now()) } )
window.addEventListener("blur", function(e) {console.log("blurred at " + performance.now()) } )
Update:
In the link to the possible duplicate is a link to the W3 Page Visibility doc here.
It says to use the visibilitychange event to check when the page is visible or hidden like so:
document.addEventListener('visibilitychange', handleVisibilityChange, false);
But there are issues:
The Document of the top level browsing context can be in one of the
following visibility states:
hidden
The Document is not visible at all on any screen. visible
The Document is at least partially visible on at least one screen. This is the same condition under which the hidden attribute is set to
false.
So it explains why it's not firing when switching apps. But even when switching apps and the window is completely hidden the event does not trigger (in Firefox).
So at the end of the page is this note:
The Page Visibility API enables developers to know when a Document is
visible or in focus. Existing mechanisms, such as the focus and blur
events, when attached to the Window object already provide a mechanism
to detect when the Document is the active document.
So it would seem to suggest that it's accepted practice to use focus and blur to detect window activation or app switching.
I found this answer that is close to what would be needed to make a cross browser solution but needs focus and blur (at least for Firefox).
Observation:
StackOverflow has a policy against mentioning frameworks or libraries. The answers linked here have upvotes for the "best" answer.
But these can grow outdated. Since yesterday I found mention of two frameworks (polyfills) that attempt to solve this same problem here for visibly and isVis (not creating a link). If this is a question and answer site and a valid answer is, "here is some code that works for me" but "Here is the library I created using the same code that can be kept up to date and maintained on github" is not valid then in my opinion it's missing it's goal.
I know above should probably go to meta and I have but they resist changing the status quo for some reason. Mentioning it here since it's a relevant example.
The Page lifecycle API can be used to listen for visibilitychange events.
[This event triggers] when a user navigates to a new page, switches tabs, closes a tab, minimizes or closes the browser, or switches apps on mobile operating systems. Quote
Current browser support
Reference on MDN
Is there a way to detect if the browser window is visible to the user? I know this has been asked before. However, the answers I have seen suffer from the following problems:
Using visibilityChange event. The problem with this approach is that (at least on a Mac) when one uses cmd+tab to switch between applications, this event is not fired.
Using onBlur and onFocus events. These solve the above problem. However, these also fire when a page's visibility does not change. For example, if the browser is open in one half of the screen and another application is open in the other half, then switching between these will cause these events to fire; even though the user has the browser window visible all the time.
Using onPageShow and onPageHide events - these appear quite useless for the task of visibility. For example, onPageHide does not fire either when the page is minimized, or when cmd+tab is used to switch to another application that occupies the whole window.
What is the ideal solution for checking whether the page is visible to the user given the above issues?
Thank you.
Could you use setIterval polling and document.hidden?
nice wrapper Visibility.js
I understand the event mouseup for the window just isn't there for IE 7 and 8. I was wondering if anybody has found a work-around for this or if that is even possible.
I am currently working on a project where the user can click, drag to draw a line, and if the user drags outside of the window and lets up on the mouse, the drawing transaction will be cancelled.
Your difficulty sounds like it would be more from the window losing the scope of the event.
Are you using jQuery? With jQuery you can also tag onto the mousemove event and use the "which" attribute to detect if the button is pressed. This even fires when you come back into the window. But it DOES NOT fire when you are outside of the window.
Alternatively you can use $(window).mouseleave to detect when it leaves the window. However once it has left the window you cannot detect further mouse events (that would be a horrible flaw if they could detect when you right clicked on your desktop etc).
So you are somewhat limited by the browser security implementations in ALL browsers and won't be able to bypass that... but you can add some work around events to provide a "similar" experience.
Not directly, but I believe this should work.
In your mousemove event, check the Event.buttons property. If it is zero, then the user must have released the mouse outside the window and you can cancel the drag.
I am checking the browser compatibility of this now, so this answer may be edited. My computer's being slow right now!
in my Firefox extension I try to handle the event when the browser window is activated or deactivated. Adding the events "activate" and "deactivate" to the window does basically work. But noticed that when I move the window, first "deactivate" (when I start moving) and then "activate" (when I finished moving through releasing the mouse key) occurs. For me, the whole time the window is active.
What is the best / simplest way to the "deactivate"/"activate" event pair when moving the Firefox window? Thanks a lot for any tips!
Christian
If I understand you correctly, you can use this:
window.addEventListener("blur",function(){
//mystuff
},false);
and this:
window.addEventListener("focus",function(){
//mystuff
},false);
I finally decided to user timer-based solution: I don't handle DEACTIVE events at once, but only if there weren't any ACTIVATE events after, say ten, seconds. So only after ten seconds I consider a window as deactivated. Resizing/Moving is typically done in way less than 10 seconds. No the optimal solution, of course, but serves my purpose sufficiently.
I have a real-time app where I am animating certain elements on the screen back and forth upon certain websocket-enabled events firing (e.g event "moveLeft" and event "moveRight"). When the user visits another browser tab and returns after many of these events have fired, they see the entire sequence of animation carry out (using .animate() upon each event firing) even though they are no longer relevant to the user. What I would like instead is for the animations to effectively happen while the user is tabbed away so that when they revisit the tab, they see the current world state and simply miss all those animations that were triggered while in another browser tab.
I can't seem to find any documentation on this issue; it bears similarity to the solution where you need to call .stop() before animating other mutually exclusive things so that you get don't a buildup after excessive mouseover events, but that is not really applicable here. Any tips would be greatly appreciated.
There is a similar question here: slideshow goes crazy if you tab away
In your case, since websockets trigger the animations, one solution could be to watch if the window has focus and only trigger the animations when it's in focus.