diff --git a/regression/issue-353.html b/regression/issue-353.html new file mode 100644 index 000000000000..8410adf4ab6b --- /dev/null +++ b/regression/issue-353.html @@ -0,0 +1,18 @@ + + + + + + test + test + + diff --git a/src/AngularPublic.js b/src/AngularPublic.js index b62483f87c71..cc901d6d278c 100644 --- a/src/AngularPublic.js +++ b/src/AngularPublic.js @@ -12,12 +12,6 @@ angularService('$browser', function($log){ if (!browserSingleton) { browserSingleton = new Browser(window, jqLite(window.document), jqLite(window.document.body), XHR, $log); - var addPollFn = browserSingleton.addPollFn; - browserSingleton.addPollFn = function(){ - browserSingleton.addPollFn = addPollFn; - browserSingleton.startPoller(100, function(delay, fn){setTimeout(delay,fn);}); - return addPollFn.apply(browserSingleton, arguments); - }; browserSingleton.bind(); } return browserSingleton; diff --git a/src/Browser.js b/src/Browser.js index b10c43cf34ca..6c64a419bb32 100644 --- a/src/Browser.js +++ b/src/Browser.js @@ -139,7 +139,8 @@ function Browser(window, document, body, XHR, $log) { ////////////////////////////////////////////////////////////// // Poll Watcher API ////////////////////////////////////////////////////////////// - var pollFns = []; + var pollFns = [], + pollTimeout; /** * @workInProgress @@ -160,11 +161,13 @@ function Browser(window, document, body, XHR, $log) { * @param {function()} fn Poll function to add * * @description - * Adds a function to the list of functions that poller periodically executes + * Adds a function to the list of functions that poller periodically executes, + * and starts polling if not started yet. * * @returns {function()} the added function */ self.addPollFn = function(fn) { + if (!pollTimeout) self.startPoller(100, setTimeout); pollFns.push(fn); return fn; }; @@ -185,7 +188,7 @@ function Browser(window, document, body, XHR, $log) { self.startPoller = function(interval, setTimeout) { (function check(){ self.poll(); - setTimeout(check, interval); + pollTimeout = setTimeout(check, interval); })(); }; @@ -247,7 +250,9 @@ function Browser(window, document, body, XHR, $log) { * @return {function()} Returns the registered listener fn - handy if the fn is anonymous. */ self.onHashChange = function(listener) { - if ('onhashchange' in window) { + // IE8 comp mode returns true, but doesn't support hashchange event + var dm = window.document.documentMode; + if ('onhashchange' in window && (!isDefined(dm) || dm >= 8)) { jqLite(window).bind('hashchange', listener); } else { var lastBrowserUrl = self.getUrl(); diff --git a/test/BrowserSpecs.js b/test/BrowserSpecs.js index 45fb0ed9270c..b4f0ab4eb42c 100644 --- a/test/BrowserSpecs.js +++ b/test/BrowserSpecs.js @@ -4,6 +4,7 @@ describe('browser', function(){ function fakeSetTimeout(fn) { setTimeoutQueue.push(fn); + return Math.random(); } fakeSetTimeout.flush = function() { @@ -371,6 +372,10 @@ describe('browser', function(){ }); describe('poller', function(){ + beforeEach(function() { + spyOn(browser, 'startPoller'); + }); + it('should call all fns on poll', function(){ var log = ''; browser.addPollFn(function(){log+='a';}); @@ -386,6 +391,7 @@ describe('browser', function(){ var log = ''; var setTimeoutSpy = jasmine.createSpy('setTimeout'); browser.addPollFn(function(){log+='.';}); + browser.startPoller.andCallThrough(); browser.startPoller(50, setTimeoutSpy); expect(log).toEqual('.'); expect(setTimeoutSpy.mostRecentCall.args[1]).toEqual(50); @@ -398,6 +404,22 @@ describe('browser', function(){ var returnedFn = browser.addPollFn(fn); expect(returnedFn).toBe(fn); }); + + it('should auto start poller when first fn registered', function() { + browser.addPollFn(function() {}); + + expect(browser.startPoller).toHaveBeenCalled(); + expect(browser.startPoller.callCount).toBe(1); + }); + + it('should auto start poller only when first fn registered', function() { + browser.startPoller.andCallThrough(); + browser.addPollFn(function() {}); + browser.addPollFn(function() {}); + browser.addPollFn(function() {}); + + expect(browser.startPoller.callCount).toBe(1); + }); }); @@ -405,9 +427,13 @@ describe('browser', function(){ it('should use $browser poller to detect url changes when onhashchange event is unsupported', function() { - fakeWindow = {location: {href:"http://server"}}; + fakeWindow = { + location: {href:"http://server"}, + document: {} + }; browser = new Browser(fakeWindow, {}, {}); + browser.startPoller = function() {}; var events = []; @@ -442,7 +468,8 @@ describe('browser', function(){ onHashChngListener = listener; }, removeEventListener: angular.noop, - detachEvent: angular.noop + detachEvent: angular.noop, + document: {} }; fakeWindow.onhashchange = true; @@ -466,5 +493,24 @@ describe('browser', function(){ jqLite(fakeWindow).dealoc(); } }); + + // asynchronous test + it('should fire onHashChange when location.hash change', function() { + var callback = jasmine.createSpy('onHashChange'); + browser = new Browser(window, {}, {}); + browser.onHashChange(callback); + + window.location.hash = 'new-hash'; + browser.startPoller(100, setTimeout); + + waitsFor(function() { + return callback.callCount; + }, 'onHashChange callback to be called', 1000); + + runs(function() { + if (!jQuery) jqLite(window).dealoc(); + window.location.hash = ''; + }); + }); }); });