stop animation on window blur - javascript

I have the following code, it fades elements in and out in a repeating cycle. When the tab is inactive the text within the divs piles up on top of each other for a split second before being cleared when the tab is activated again. Is there a way to stop this animation when the window blurs and start it again on focus?
(cycle = function () {
setTimeout(function(){$('#right').fadeOut(1000)},10000);
setTimeout(function(){$('right').fadeIn(1000)}, 11000);
setTimeout(function(){$('#left').fadeOut(1000)},13000);
setTimeout(function(){$('#left').fadeIn(1000)},14000);
setTimeout(function(){$('#left').fadeOut(1000)},15000);
setTimeout(function(){$('#left').fadeIn(1000)},17000);
})();

I gave a suggestion in a comment, but then remembered that that solution is not necessarily cross-browser compatible, as I had come across it before, thus the creation of my plugin.
Suffice it to say, $(window).blur() and focus do not always work as expected on all browsers. I don't remember the exact list of problems I ran into, but I know some were things like; clicking on another tab (in FF, i think) did not trigger the blur, clicking on another program would trigger the blur despite the fact my main browser window was still open and that tab had focus, it ddnt have Windows Focus, etc...
The following plugin I created might be helpful in that I've filed it down to work in "most" browsers and versions (not tested on all versions) and it functions exactly as we expect where I work. It only goes blur if the exact browser window's tab loses focus to another tab of the same browser. And of course vice versa with focus.
See jsFiddle Example usage and unminified code
Minified Plugin:
Simply Add to a js file to be called after jquery or place at top of your code
(function(jQuery){jQuery.winFocus||(jQuery.extend({winFocus:function(b){function c(a){a=a||window.event;a.hidden=a.type in{focus:"visible",focusin:"visible",pageshow:"visible",blur:"hidden",focusout:"hidden",pagehide:"hidden"}?"focusout"===a.type:this[d];jQuery(window).data("visible",!a.hidden);jQuery.winFocus.methods.exeCB(a)}var d="hidden";d in document?document.addEventListener("visibilitychange",c):(d="mozHidden")in document?document.addEventListener("mozvisibilitychange",c):(d="webkitHidden")in document?
document.addEventListener("webkitvisibilitychange",c):(d="msHidden")in document?document.addEventListener("msvisibilitychange",c):"onfocusin"in document?document.onfocusin=document.onfocusout=c:window.onpageshow=window.onpagehide=window.onfocus=window.onblur=c;for(x in arguments)"object"==typeof arguments[x]?(arguments[x].blur&&(jQuery.winFocus.methods.blur=arguments[x].blur),arguments[x].focus&&(jQuery.winFocus.methods.focus=arguments[x].focus),arguments[x].blurFocus&&(jQuery.winFocus.methods.blurFocus=
arguments[x].focus)):"function"==typeof arguments[x]&&(void 0===jQuery.winFocus.methods.blurFocus?jQuery.winFocus.methods.blurFocus=arguments[x]:(jQuery.winFocus.methods.blur=jQuery.winFocus.methods.blurFocus,jQuery.winFocus.methods.blurFocus=void 0,jQuery.winFocus.methods.focus=arguments[x]))}}),jQuery.winFocus.methods={blurFocus:void 0,blur:void 0,focus:void 0,exeCB:function(b){jQuery.winFocus.methods.blurFocus?jQuery.winFocus.methods.blurFocus(b,!b.hidden):b.hidden?jQuery.winFocus.methods.blur&&
jQuery.winFocus.methods.blur(b):jQuery.winFocus.methods.focus&&jQuery.winFocus.methods.focus(b)}})})(jQuery);
Also: #line-o 's referenced SO Question is where I was first inspired to write this plugin and I also have this plugin answer posted there. lol

Take a look at the Visibility API for current browser. You'll still need a fallback for older ones (namely IEs).
Or you might find a solution here:
Is there a way to detect if a browser window is not currently active?

Related

IE8 only jumps back to top of previous page not where I was before (but only with JS on)

I have a horrible, scattered page with lots of JavaScript:
It has a list view and if you like you can watch one of the items in the list in detail.
The problem is now if I want to go back from the details view to the list view by using the browser back button I get different results.
In Chrome and Firefox, even in IE7 I will end up where I clicked, but not so in IE8.
To make it even more confusing, if I switch JavaScript off it works for IE8 as well.
The problem is now I don't now where to search. Does somebody know this problem or at least a JavaScript method or function which could affect this?
It is difficult to provide a definitive answer without the code. A tentative answer based on past experiences with IE:
IEs have different behaviors, especially IE8 which is at the crossing of the old and all but standard versions [IE6-, IE7] and the newer IE9 that better sticks to standards. In particular in Javascript, IEs may be picky compared to non-IE browsers.
That back behavior could happen if a JS error is triggered either when you leave the page (thanks to the link click), or when you come back (which is easier to spot)
Check if an error occurs when leaving (or coming back) at the bottom of the page
The click action could be delayed thanks to setTimeout which function would set window.location.href to give you enough time to spot an error before the page is left
If the redirect is "manual" (like window.location.href= as opposed to a simple <a> tag) Try to add a try {} catch around the code that run after the element is clicked (like with this onbeforeunload bug).

How do I debug and inspect things that change on response to mouseclicks or focus changes?

I'm currently toying around with some autocomplete form fields, and am finding it very hard to inspect the generated drop down items. As soon as I click on the "inspect element" button or try to right click on the dropdowns, the original autocomplete input runs an onclick event (or something that triggers on a focus change) and hides, deletes or otherwise modifies the element I was trying to inspect.
Is there a way to work with the debugger so that the mouseclicks and other commands I give to it don't get intercepted by the script I'm trying to debug?
I currently have this kind of problem on both Firebug and on Chrome's inspector. The only solution I can think right now would be setting some smart breakpoints inside the appropriate event handlers but that is hard to do if I don't know what event handlers to look for or where they are hidden in the original code...
You could set a breakpoint and inspect after it is triggered, I have noticed that freezes the DOM.
You need to use breakpoints. As far as tracking down what's happening where, Chrome's "Call Stack" window can be very helpful.
Cheers
In Firebug you have a Break on next item in Script panel. Since Firebug 1.10, there's a keyboard shortcut for this: Ctrl+Alt+B on Windows (it works even if focus is in the page, not in Firebug).
You'll probably need to have Script panel focused in Firebug since this is a shared shortcut for Break on... which differs in each panel.
It generally freezes the DOM although it's not 100% reliable.
It's also not ideal because it will stop at any JavaScript execution, and will not be helpful if there is some aggressive polling in the background, or global capturing of keyboard events. Anyway it's still better than nothing.
Chrome pauses Javascript execution on F8; it took a bit of repetition but pressing F8 at the right time prevented JS from defocusing the element.
If you are having problem selecting the element, you can try cmd + shift + c on Mac to select the element without right clicking it.
If its DOM manipulation problem, you might try to force state on the input element by right clicking on the element in the Elements panel and set force state to focus.
Open the docked DevTools first (the undocked approach will not work due to the OS limitations.)
Once the autocomplete box is displayed, right-click it and select "Inspect Element" in the context menu. The focus will move to the DevTools but the autocomplete box will still be shown (this worked for me on Linux, tip-of-tree Chromium, M25. Your mileage may vary.)
/**
* Utility to freeze actual DOM state, for example dropdown menu
*/
function easyBreak() {
function doBreak() {
// put breakpoint here to freeze actual dom and write to console easyBreak()
// you have 3 seconds to get to desired state
var a = 0;
}
window.setTimeout(doBreak, 3000);
}
You could use DOM breakpoints.
I'm having a similar case here : I want to inspect dropdown items that only show when the input has focus.
On Chrome, I right-click on the parent element and choose Break on > Subtree modifications.
It will pause - like it does with JS breakpoints - anytime the DOM changes within that parent. You can then inspect the children while the DOM is frozen.

How do I disable body.blur() in IE8?

I work on an enterprise web application that runs in IE8. It appears blur() is being called on the body causing the IE window to be sent to the background. Unfortunately this code is in a portion of the application that is controlled by the vendor.
Is there any possible way to prevent blur() from being called on the body without modifying the code that is actually calling body.blur()?
Since this is an enterprise application, solutions outside of changes in the application itself are acceptable; Such as changes to IE8 settings, registry, etc.
You should be able to hard code blur to a dummy method. If you can get in before it is called, just call body.blur = function() {}; (assuming body is pointing to your DOM body element).
Using jQuery you could simply block the event :
$('body').blur(function(e) { e.preventDefault(); });
If using Firefox is an option, i have two answers where i propose replacing the function using Greasemonkey.
Using javascript to create a keylistener hotkey for facebook page "like"
Greasemonkey script to replace jQuery plugin function?
If you have to use IE, you might need to change the page itself.
(I know there is Trixie and IE7pro for IE, but never used).
I had an issue when using javaScript editor:CLEditor, if I use jQuery blur() method on it, the IE window goes to the background. CLEditor has it's iframe which has its own body. When you extract that body and use body.blur(), IE browser will go to the background.
Other browsers are not showing that behavior, so it is better to use FF, or Chrome if you are experiencing this.
If you remove body.blur(), probably you would have less problems with IE than you have now, but still you could experience some minor bugs (something is not loosing focus at certain point), but I suppose you could live with it. However if blur() event is enriched with some logic, it could be problem - then find its definition and move logic to some other event that is started with the browser (onload, or ready).
document.body.blur=function(){document.body.focus()}

Google Chrome duplicates JavaScript 'focus' event

I've noticed a strange issue with how Chrome handles javascript focus event. The fact is, it continuosly triggers focus event, even if it occurs only once. I've made a bit of research here and found questions where people run into the same issue when using alert(). When they close the alert window, the focus returns to their inputs and a handler triggers again and again. In my case, the problem is different, as I am using console.log(), and from time to time I get the same log 2 or even 3 times. I've noticed it usually happens when I clear the console, and then focus on an element. When I try to repeat it, it does not occur any more.
The scenario:
Clear console
Focus on element (2 or 3 console messages)
Focus on other identical element or unfocus and focus again on the
same one (no problems)
Clear console
Focus on element (2 or 3 console messages - the problem is back!)
I've created a jsfiddle, please check it out:
http://jsfiddle.net/ffuWT/3/
The question is, what is the reason for this issue and how can I work around it?
Creepy how these things can happen. I've run into this exact issue at work today, but have quickly written this off suspecting dodgy event listening and propagation in a 3rd-party plugin (jQuery customInput). I'll double-check your jsfiddle tomorrow.
I'm unable to recreate your exact output on my currently available setup (Chrome v17 on a Mac) but I do have a theory to share. In your scenario and in Ben Lee's comment the consistent part is shifting focus to another window (console in your case).
Check out http://www.quirksmode.org/dom/events/blurfocus.html under "Window + focusable element":
If the window is sent backward while a focusable element is focused,
blur events should fire on both. If the window is brought forward
again, focus events should fire on both.
And next, in the compatibility table it's noted that
Safari Windows fires two focus events.
Maybe Chrome finally got this "feature" too, coming from the Webkit family and all?
I was able to recreate the problem (using your jsFiddle) and from what I can see it only occurs when you click the select without having focus on/in the result frame.
Click within the frame but not on the selects before you click to expand one of the selects and you´ll only see one line logged.
You can also append /show to the jsFiddle URL to view the result in a separate window.
It seems like focusing the window by clicking on a select control triggers the event multiple times.
Open this demo and unfocus the browser window (by clicking the desktop, taskbar or another window) and then click on one of the selects to expand its options and view the console.
Using Chrome 17.0.963.79 m.

Event for browser tab hidden/shown?

Is there any DOM event for when the browser tab loses/gains focus? I know there are the blur and focus events on window, but they also fire when the browser window as a whole loses focus. The browser might then be still visible to the user. Of course such an event would be browser specific, but that's ok.
The reason why I want this is because I run animations that might consume quite some CPU time. When the browser tab is not visible there is no reason to continue animating. Now I know that modern browsers reduce the timer resolution of background tabs, but I could actually pause the animation, so that no CPU time whatsoever is consumed.
In case you are wondering, this is what I'm writing:
http://panzi.github.com/Browser-Ponies/
At least Google Chrome supports a webkitvisibilitychange event and a document.webkitHidden property. See the visibility API. But it seems only to fire when the shown tab changes, not when the whole window is minimized. There also seems to be a visibilitychange event for Internet Explorer, but the documentation doesn't say anything about it.
The closest thing I believe you'll find is the top answer here:
Is there a way track the focus on tab with Javascript?
Now they have exactly what was needed:
https://developer.mozilla.org/en-US/docs/Web/Guide/User_experience/Using_the_Page_Visibility_API

Categories

Resources