diff --git a/lib/visibility.core.js b/lib/visibility.core.js index 4fd79d8..1f41aca 100644 --- a/lib/visibility.core.js +++ b/lib/visibility.core.js @@ -51,6 +51,8 @@ // callback will be original event object, second will be visibility // state name. // + // Return listener ID to unbind listener by `unbind` method. + // // If Page Visibility API doesn’t supported method will be return false // and callback never will be called. // @@ -63,9 +65,21 @@ if ( !this.isSupported() ) { return false; } - this._changeCallbacks.push(callback); + this._lastCallback += 1; + var number = this._lastCallback; + this._callbacks[number] = callback; this._setListener(); - return true; + return number; + }, + + // Remove `change` listener by it ID. + // + // var id = Visibility.change(function(e, state) { + // firstChangeCallback(); + // Visibility.unbind(id); + // }); + unbind: function (id) { + delete this._callbacks[id]; }, // Call `callback` in any state, expect “prerender”. If current state @@ -143,8 +157,11 @@ // by `_setListener` method. _listening: false, + // Last timer number. + _lastCallback: -1, + // Callbacks from `change` method, that wait visibility changes. - _changeCallbacks: [], + _callbacks: { }, // Callbacks from `onVisible` method, that wait when page become to be // visible. @@ -200,8 +217,8 @@ var isHidden = this.hidden(), state = this.state(); - for ( var i = 0; i < this._changeCallbacks.length; i++ ) { - this._changeCallbacks[i].call(this._doc, event, state); + for ( var i in this._callbacks ) { + this._callbacks[i].call(this._doc, event, state); } if ( !isHidden ) { diff --git a/lib/visibility.timers.js b/lib/visibility.timers.js index ab3219b..7b31bf4 100644 --- a/lib/visibility.timers.js +++ b/lib/visibility.timers.js @@ -98,7 +98,7 @@ }, // Last timer number. - _lastTimer: 0, + _lastTimer: -1, // Callbacks and intervals added by `every` method. _timers: { }, diff --git a/test/visibility_spec.coffee b/test/visibility_spec.coffee index 0390d52..cfb5742 100644 --- a/test/visibility_spec.coffee +++ b/test/visibility_spec.coffee @@ -5,8 +5,9 @@ describe 'Visibility', -> Visibility._chechedPrefix = null Visibility._listening = false Visibility._timersInitialized = false - Visibility._changeCallbacks = [] - Visibility._lastTimer = 0 + Visibility._lastCallback = -1 + Visibility._callbacks = [] + Visibility._lastTimer = -1 Visibility._timers = { } Visibility._hiddenBefore = false Visibility._setInterval = -> @@ -80,7 +81,7 @@ describe 'Visibility', -> sinon.spy(Visibility, '_setListener') callback = sinon.spy() - Visibility.change(callback).should.be.true + Visibility.change(callback).should.not.be.false Visibility._setListener.should.have.been.called event = { } @@ -93,6 +94,24 @@ describe 'Visibility', -> callback.should.have.been.calledTwice callback.getCall(1).calledWith(event, 'hidden').should.be.true + describe '.unbind()', -> + + it 'should remove listener', -> + Visibility._chechedPrefix = 'webkit' + sinon.spy(Visibility, '_setListener') + + callback1 = sinon.spy() + callback2 = sinon.spy() + + id1 = Visibility.change(callback1) + id2 = Visibility.change(callback2) + + Visibility.unbind(id2) + + Visibility._onVisibilityChange({ }) + callback1.should.have.been.called + callback2.should.not.have.been.called + describe '.afterPrerendering()', -> it 'should run afterPrerendering callback immediately without API', ->