mirror of
https://github.com/zhigang1992/angular.js.git
synced 2026-04-23 11:37:38 +08:00
fix($browser): don’t use history api when only the hash changes
IE10/11 have the following problem: When changing the url hash via `history.pushState()` and then reverting the hash via direct changes to `location.href` (or via a link) does not fire a `hashchange` nor `popstate` event. This commit changes the default behavior as follows: Uses `location.href`/`location.replace` if the new url differs from the previous url only in the hash fragment or the browser does not support history API. Use `history.pushState`/ `history.replaceState` otherwise. Fixes #9143 Closes #9406
This commit is contained in:
@@ -153,8 +153,13 @@ function Browser(window, document, $log, $sniffer) {
|
||||
// setter
|
||||
if (url) {
|
||||
if (lastBrowserUrl == url) return;
|
||||
var sameBase = lastBrowserUrl && stripHash(lastBrowserUrl) === stripHash(url);
|
||||
lastBrowserUrl = url;
|
||||
if ($sniffer.history) {
|
||||
// Don't use history API if only the hash changed
|
||||
// due to a bug in IE10/IE11 which leads
|
||||
// to not firing a `hashchange` nor `popstate` event
|
||||
// in some cases (see #9143).
|
||||
if (!sameBase && $sniffer.history) {
|
||||
if (replace) history.replaceState(null, '', url);
|
||||
else {
|
||||
history.pushState(null, '', url);
|
||||
|
||||
@@ -720,6 +720,9 @@ function $LocationProvider(){
|
||||
|
||||
if (absHref && !elm.attr('target') && !event.isDefaultPrevented()) {
|
||||
if ($location.$$parseLinkUrl(absHref, relHref)) {
|
||||
// We do a preventDefault for all urls that are part of the angular application,
|
||||
// in html5mode and also without, so that we are able to abort navigation without
|
||||
// getting double entries in the location history.
|
||||
event.preventDefault();
|
||||
// update location manually
|
||||
if ($location.absUrl() != $browser.url()) {
|
||||
|
||||
@@ -445,6 +445,17 @@ describe('browser', function() {
|
||||
expect(locationReplace).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should set location.href and not use pushState when the url only changed in the hash fragment to please IE10/11', function() {
|
||||
sniffer.history = true;
|
||||
browser.url('http://server/#123');
|
||||
|
||||
expect(fakeWindow.location.href).toEqual('http://server/#123');
|
||||
|
||||
expect(pushState).not.toHaveBeenCalled();
|
||||
expect(replaceState).not.toHaveBeenCalled();
|
||||
expect(locationReplace).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should use location.replace when history.replaceState not available', function() {
|
||||
sniffer.history = false;
|
||||
browser.url('http://new.org', true);
|
||||
@@ -456,6 +467,17 @@ describe('browser', function() {
|
||||
expect(fakeWindow.location.href).toEqual('http://server/');
|
||||
});
|
||||
|
||||
it('should use location.replace and not use replaceState when the url only changed in the hash fragment to please IE10/11', function() {
|
||||
sniffer.history = true;
|
||||
browser.url('http://server/#123', true);
|
||||
|
||||
expect(locationReplace).toHaveBeenCalledWith('http://server/#123');
|
||||
|
||||
expect(pushState).not.toHaveBeenCalled();
|
||||
expect(replaceState).not.toHaveBeenCalled();
|
||||
expect(fakeWindow.location.href).toEqual('http://server/');
|
||||
});
|
||||
|
||||
it('should return $browser to allow chaining', function() {
|
||||
expect(browser.url('http://any.com')).toBe(browser);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user