From b3e09be58960b913fee3869bf36e7de3305bbe00 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Thu, 19 Dec 2013 16:16:53 -0700 Subject: [PATCH] feat($location): allow automatic rewriting of links to be disabled Currently, when the location provider is set to html5 mode, all links on the page are hijacked and automatically rewritten. While this may be desirable behavior in some cases (such as using ngRoute), not all cases where html5 mode are enabled imply the desire for this behavior. One example would be an application using the [ui-router](https://github.com/angular-ui/ui-router) library, with some pages that exist outside of angular. Links that are meant to go through the router use the `ui-sref` directive, so the rewrite behavior is unnecessary. Closes #5487 --- src/ng/location.js | 44 +++++++++++++++++++++++--------------- test/ng/locationSpec.js | 47 +++++++++++++++++++++++------------------ 2 files changed, 54 insertions(+), 37 deletions(-) diff --git a/src/ng/location.js b/src/ng/location.js index 8f5baf51599e..20dbe5cf738d 100644 --- a/src/ng/location.js +++ b/src/ng/location.js @@ -624,7 +624,8 @@ function $LocationProvider(){ var hashPrefix = '', html5Mode = { enabled: false, - requireBase: true + requireBase: true, + rewriteLinks: true }; /** @@ -648,15 +649,17 @@ function $LocationProvider(){ * @name $locationProvider#html5Mode * @description * @param {(boolean|Object)=} mode If boolean, sets `html5Mode.enabled` to value. - * If object, sets `enabled` and `requireBase` to respective values. - * - **enabled** – `{boolean}` – Sets `html5Mode.enabled`. If true, will rely on - * `history.pushState` to change urls where supported. Will fall back to hash-prefixed paths - * in browsers that do not support `pushState`. - * - **requireBase** - `{boolean}` - Sets `html5Mode.requireBase` (default: `true`). When - * html5Mode is enabled, specifies whether or not a tag is required to be present. If - * `enabled` and `requireBase` are true, and a base tag is not present, an error will be - * thrown when `$location` is injected. See the - * {@link guide/$location $location guide for more information} + * If object, sets `enabled`, `requireBase` and `rewriteLinks` to respective values. Supported + * properties: + * - **enabled** – `{boolean}` – (default: false) If true, will rely on `history.pushState` to + * change urls where supported. Will fall back to hash-prefixed paths in browsers that do not + * support `pushState`. + * - **requireBase** - `{boolean}` - (default: `true`) When html5Mode is enabled, specifies + * whether or not a tag is required to be present. If `enabled` and `requireBase` are + * true, and a base tag is not present, an error will be thrown when `$location` is injected. + * See the {@link guide/$location $location guide for more information} + * - **rewriteLinks** - `{boolean}` - (default: `false`) When html5Mode is enabled, disables + * url rewriting for relative linksTurns off url rewriting for relative links. * * @returns {Object} html5Mode object if used as getter or itself (chaining) if used as setter */ @@ -665,12 +668,19 @@ function $LocationProvider(){ html5Mode.enabled = mode; return this; } else if (isObject(mode)) { - html5Mode.enabled = isBoolean(mode.enabled) ? - mode.enabled : - html5Mode.enabled; - html5Mode.requireBase = isBoolean(mode.requireBase) ? - mode.requireBase : - html5Mode.requireBase; + + if (isBoolean(mode.enabled)) { + html5Mode.enabled = mode.enabled; + } + + if (isBoolean(mode.requireBase)) { + html5Mode.requireBase = mode.requireBase; + } + + if (isBoolean(mode.rewriteLinks)) { + html5Mode.rewriteLinks = mode.rewriteLinks; + } + return this; } else { return html5Mode; @@ -763,7 +773,7 @@ function $LocationProvider(){ // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser) // currently we open nice url link and redirect then - if (event.ctrlKey || event.metaKey || event.which == 2) return; + if (!html5Mode.rewriteLinks || event.ctrlKey || event.metaKey || event.which == 2) return; var elm = jqLite(event.target); diff --git a/test/ng/locationSpec.js b/test/ng/locationSpec.js index f66ce9c65fda..d86008639b8a 100644 --- a/test/ng/locationSpec.js +++ b/test/ng/locationSpec.js @@ -1279,6 +1279,19 @@ describe('$location', function() { }); + it ('should not rewrite links when rewriting links is disabled', function() { + configureService('/a?b=c', true, true, '', 'some content', false); + inject( + initBrowser(), + initLocation(), + function($browser) { + browserTrigger(link, 'click'); + expectNoRewrite($browser); + } + ); + }); + + it('should rewrite full url links to same domain and base path', function() { configureService({linkHref: 'http://host.com/base/new', html5Mode: true}); inject( @@ -1793,11 +1806,13 @@ describe('$location', function() { describe('html5Mode', function() { - it('should set enabled and requireBase when called with object', function() { + it('should set enabled, requireBase and rewriteLinks when called with object', function() { module(function($locationProvider) { + $locationProvider.html5Mode({enabled: true, requireBase: false, rewriteLinks: false}); expect($locationProvider.html5Mode()).toEqual({ - enabled: false, - requireBase: true + enabled: true, + requireBase: false, + rewriteLinks: false }); }); @@ -1809,12 +1824,14 @@ describe('$location', function() { module(function($locationProvider) { $locationProvider.html5Mode({ enabled: 'duh', - requireBase: 'probably' + requireBase: 'probably', + rewriteLinks: 'nope' }); expect($locationProvider.html5Mode()).toEqual({ enabled: false, - requireBase: true + requireBase: true, + rewriteLinks: true }); }); @@ -1830,19 +1847,8 @@ describe('$location', function() { expect($locationProvider.html5Mode()).toEqual({ enabled: false, - requireBase: true - }); - }); - - inject(function(){}); - }); - - - it('should default to enabled:false and requireBase:true', function() { - module(function($locationProvider) { - expect($locationProvider.html5Mode()).toEqual({ - enabled: false, - requireBase: true + requireBase: true, + rewriteLinks: true }); }); @@ -1850,11 +1856,12 @@ describe('$location', function() { }); - it('should return html5Mode object when called without value', function() { + it('should default to enabled:false, requireBase:true and rewriteLinks:true', function() { module(function($locationProvider) { expect($locationProvider.html5Mode()).toEqual({ enabled: false, - requireBase: true + requireBase: true, + rewriteLinks: true }); });