Add Visibility.change(callback) to listen visibility state changes

This commit is contained in:
Andrey A.I. Sitnik
2011-06-17 12:00:37 +04:00
parent 2960c2cee4
commit ca62102f60
2 changed files with 59 additions and 4 deletions

View File

@@ -62,6 +62,9 @@
return this._doc[this._name(name)]
},
// Callbacks from change method, that wait visibility changes.
_changeCallbacks: [],
// Callbacks from onVisible method, that wait when page become to be
// visible.
_onVisibleCallbacks: [],
@@ -71,12 +74,18 @@
_listening: false,
// Listener for visibilitychange event.
_onVisibilityChange: function() {
_onVisibilityChange: function(event) {
var state = this.state();
for ( var i = 0; i < this._changeCallbacks.length; i++ ) {
this._changeCallbacks[i].call(this._doc, event, state);
}
if ( !this.hidden() ) {
for ( var i = 0; i < this._onVisibleCallbacks.length; i++ ) {
this._onVisibleCallbacks[i]()
this._onVisibleCallbacks[i]();
}
this._onVisibleCallbacks = []
this._onVisibleCallbacks = [];
}
},
@@ -116,6 +125,21 @@
return this._prop('visibilityState');
},
// Call callback when visibility will be changed. First argument of
// callback will be original event object, second will be visibility
// state name.
// If Page Visibility API doesn't supported method will be return false
// and callback never will be called.
// It is just proxy to visibilitychange event, but use vendor prefix.
change: function (callback) {
if ( !this.support() ) {
return false;
}
this._changeCallbacks.push(callback);
this._setListener();
return true;
},
// Call callback only when page become to visible for user or
// call it now if page is visible now or Page Visibility API
// doesn't supported.
@@ -127,7 +151,7 @@
return true;
}
this._onVisibleCallbacks.push(callback);
this._setListener()
this._setListener();
}
};

View File

@@ -4,6 +4,7 @@ describe('Visibility', function () {
beforeEach(function () {
Visibility._chechedPrefix = null;
Visibility._listening = false;
Visibility._changeCallbacks = [];
Visibility._doc = document = {
addEventListener: function() { }
};
@@ -101,6 +102,36 @@ describe('Visibility', function () {
expect( Visibility._onVisibilityChange ).toHaveBeenCalled();
});
it('should return false on change method without API support', function () {
spyOn(Visibility, 'support').andReturn(false);
spyOn(Visibility, '_setListener');
var callback = jasmine.createSpy();
expect( Visibility.change(callback) ).toEqual(false);
expect( callback ).not.toHaveBeenCalled();
expect( Visibility._setListener ).not.toHaveBeenCalled();
});
it('should call callback on visible state shanges', function () {
Visibility._chechedPrefix = 'webkit';
spyOn(Visibility, '_setListener');
var callback = jasmine.createSpy();
expect( Visibility.change(callback) ).toEqual(true);
expect( Visibility._setListener ).toHaveBeenCalled();
var event = { };
document.webkitVisibilityState = 'visible';
Visibility._onVisibilityChange(event);
expect( callback ).toHaveBeenCalledWith(event, 'visible');
document.webkitVisibilityState = 'hidden';
Visibility._onVisibilityChange(event);
expect( callback.callCount ).toEqual(2);
expect( callback.mostRecentCall.args ).toEqual([event, 'hidden']);
});
it('should call onVisible callback now without API support', function () {
spyOn(Visibility, 'support').andReturn(false);
spyOn(Visibility, '_setListener');