PDA

View Full Version : [2.2] Ext.Viewport - utilizing browser focus/blur events



ThorstenSuckow
13 Apr 2009, 3:39 AM
Here is a very simple yet useful method to add the focus/blur event to Ext.Viewport: The events get fired when the browser window running your Ext application gains/loses focus. I use it to sign out the current user automatically once the application has lost the focus for ~ 15 minutes:



/**
* Adds focus/blur events to Ext.Viewport which generally translate to
* browser window focus/blur.
*
* @author Thorsten Suckow-Homberg <ts@siteartwork.de>
*/
Ext.Viewport.prototype.initComponent = Ext.Viewport.prototype.initComponent.createInterceptor(
function() {
this.addEvents(
/**
* @event blur
* Fires when the viewport loses its focus, i.e. when the browser window/tab
* loses its focus
* @param {Ext.Viewport}
* @param {HTMLElement} lastActiveElement
*/
'blur',
/**
* @event focus
* @event blur
* Fires when the viewport gains focus, i.e. when the browser window/tab
* gains focus
* @param {Ext.Viewport}
* @param {HTMLElement} lastActiveElement
*/
'focus'
);

var focusEl = window;
var eventNames = ['focus', 'blur'];

if (Ext.isIE) {
focusEl = document;
eventNames = ['focusin', 'focusout'];
}

Ext.EventManager.on(focusEl, eventNames[0], function(e) {
if (this._hasFocus) {
return;
}
this._hasFocus = true;
this.fireEvent('focus', this, this._activeElement);
}, this, {stopPropagation : true});

Ext.EventManager.on(focusEl, eventNames[1], function(e) {
if (this._activeElement != document.activeElement) {
this._activeElement = document.activeElement;
// ie detects focus loss if current activeElement
// equals to last active element
if (Ext.isIE) {
return;
}
}
this._hasFocus = false;
this.fireEvent('blur', this, this._activeElement);
}, this, {stopPropagation : true});

this._activeElement = document.activeElement;
}
);


Put this code in your global Ext overrides file and you are able to listen to Ext.Viewports focus/blur events.


Tested with:
IE7
Mozilla FF 3
Safari (Windows)
Chrome

moegal
29 May 2009, 8:44 AM
This looks really usefull. Can I change this to override Ext.Desktop? I run an internal chat and it would be nice to know if the chat message has been seen or not.

Thanks, Marty

ThorstenSuckow
29 May 2009, 8:48 AM
This looks really usefull. Can I change this to override Ext.Desktop? I run an internal chat and it would be nice to know if the chat message has been seen or not.

Thanks, Marty

Well, the above implementation fires the events if the browser window loses/gains focus.

Dunno about Ext.Desktop, but I guess it uses Ext.Viewport as it's "bottom layer" - best way would be to test it, otherwise you must be more specific about what you want to do. ~o)

mystix
29 May 2009, 9:38 AM
@mindpatterns, could you explain this portion of your code?
i don't quite follow the logic behind it:


Ext.EventManager.on(focusEl, eventNames[1], function(e) {
if (this._activeElement != document.activeElement) {
this._activeElement = document.activeElement;

// ie detects focus loss if current activeElement
// equals to last active element
if (Ext.isIE) {
return;
}
}
this._hasFocus = false;
this.fireEvent('blur', this, this._activeElement);
}, this, {stopPropagation : true});


p.s. which version of Safari / Chrome did you test on?
as far as i know document.activeElement is not supported on Firefox 2 / Safari 3.2x / Opera, so you might want to take a look at this workaround:
http://ajaxandxml.blogspot.com/2007/11/emulating-activeelement-property-with.html
until the HTML5 spec is fully implemented (and soon i hope) by all modern (read non-crappy) browsers.

ThorstenSuckow
30 May 2009, 2:14 AM
@mindpatterns, could you explain this portion of your code?
i don't quite follow the logic behind it:


Well, IE tells that the window has lost focus if the document.activeElement does not change to the previous activeElement. Means: The condition checks whether the previous activeElement equals to the document.activeElement. If they do not equal, then some element within the browser window must have gained the focus - but if they are equal, then no other element in the window has gained focus and IE tells that the browser window lost the focus. The _activeElement in the override is just there to support the IE implementation of this IE "focusout" event thingy.

I hope my explanation makes it somewhat clearer... :)



p.s. which version of Safari / Chrome did you test on?
as far as i know document.activeElement is not supported on Firefox 2 / Safari 3.2x / Opera, so you might want to take a look at this workaround:
http://ajaxandxml.blogspot.com/2007/11/emulating-activeelement-property-with.html
until the HTML5 spec is fully implemented (and soon i hope) by all modern (read non-crappy) browsers.

Yes, you are absolutely right. In my listeners (listeners for Ext.Viewport focus/blur) I did not consider the second parameter that gets passed with the event, thus I never inspected it in browsers other than IE. I don't know if the second parameter (_activeElement) is quite neccessary, so it could be removed from fireEvent... would save some overhead regarding implementing it cross browser. Thoughts?

sjetti
2 Mar 2010, 9:12 AM
Hi, I also want to use it to sign out the current user automatically once the application has lost the focus / idle for ~ 15 minutes. Do you have a sample code of client side implementation of the feature...?
Thank you.