aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorIgor Minar2011-01-13 15:32:13 -0800
committerIgor Minar2011-01-13 16:58:35 -0800
commit23875cb330945788f2d290fd2063eb3d5c20e260 (patch)
tree0fe22574a0603ec80b4c012fa18766eb02951437 /src
parentb0be87f663e8684c1369e1bff740c1750ba17080 (diff)
downloadangular.js-23875cb330945788f2d290fd2063eb3d5c20e260.tar.bz2
significant rewrite of the $location service
- don't update browser before and after eval instead - sync location properties before eval - sync location properties and update browser after eval - added tests - symplified the code - removed $location.toString() because it was not idempotent and useless This resolves the issue with issuing two $route.onHashChange calls when the $location was updated with a hashPath that needs to be encoded
Diffstat (limited to 'src')
-rw-r--r--src/Browser.js2
-rw-r--r--src/services.js76
2 files changed, 34 insertions, 44 deletions
diff --git a/src/Browser.js b/src/Browser.js
index eb6afb3c..671ec1cc 100644
--- a/src/Browser.js
+++ b/src/Browser.js
@@ -232,6 +232,7 @@ function Browser(window, document, body, XHR, $log) {
* {@link angular.service.$location $location service} to monitor hash changes in angular apps.
*
* @param {function(event)} listener Listener function to be called when url hash changes.
+ * @return {function()} Returns the registered listener fn - handy if the fn is anonymous.
*/
self.onHashChange = function(listener) {
if ('onhashchange' in window) {
@@ -245,6 +246,7 @@ function Browser(window, document, body, XHR, $log) {
}
});
}
+ return listener;
}
//////////////////////////////////////////////////////////////
diff --git a/src/services.js b/src/services.js
index b9325721..573eca21 100644
--- a/src/services.js
+++ b/src/services.js
@@ -70,23 +70,18 @@ angularServiceInject("$document", function(window){
*/
angularServiceInject("$location", function($browser) {
var scope = this,
- location = {toString:toString, update:update, updateHash: updateHash},
- lastBrowserUrl = $browser.getUrl(),
- lastLocationHref,
- lastLocationHash;
-
- $browser.onHashChange(function() {
- update(lastBrowserUrl = $browser.getUrl());
- updateLastLocation();
+ location = {update:update, updateHash: updateHash},
+ lastLocation = {};
+
+ $browser.onHashChange(function() { //register
+ update($browser.getUrl());
+ copy(location, lastLocation);
scope.$eval();
- });
+ })(); //initialize
- this.$onEval(PRIORITY_FIRST, updateBrowser);
+ this.$onEval(PRIORITY_FIRST, sync);
this.$onEval(PRIORITY_LAST, updateBrowser);
- update(lastBrowserUrl);
- updateLastLocation();
-
return location;
// PUBLIC METHODS
@@ -107,7 +102,7 @@ angularServiceInject("$location", function($browser) {
* scope.$location.update({host: 'www.google.com', protocol: 'https'});
* scope.$location.update({hashPath: '/path', hashSearch: {a: 'b', x: true}});
*
- * @param {(string|Object)} href Full href as a string or hash object with properties
+ * @param {(string|Object)} href Full href as a string or object with properties
*/
function update(href) {
if (isString(href)) {
@@ -163,62 +158,55 @@ angularServiceInject("$location", function($browser) {
update(hash);
}
- /**
- * @workInProgress
- * @ngdoc method
- * @name angular.service.$location#toString
- * @methodOf angular.service.$location
- *
- * @description
- * Returns string representation - href
- */
- function toString() {
- updateLocation();
- return location.href;
- }
// INNER METHODS
/**
- * Update location object
+ * Synchronizes all location object properties.
*
* User is allowed to change properties, so after property change,
* location object is not in consistent state.
*
+ * Properties are synced with the following precedence order:
+ *
+ * - `$location.href`
+ * - `$location.hash`
+ * - everything else
+ *
* @example
* scope.$location.href = 'http://www.angularjs.org/path#a/b'
* immediately after this call, other properties are still the old ones...
*
* This method checks the changes and update location to the consistent state
*/
- function updateLocation() {
- if (location.href == lastLocationHref) {
- if (location.hash == lastLocationHash) {
+ function sync() {
+ if (!equals(location, lastLocation)) {
+ if (location.href != lastLocation.href) {
+ update(location.href);
+ return;
+ }
+ if (location.hash != lastLocation.hash) {
+ var hash = parseHash(location.hash);
+ updateHash(hash.path, hash.search);
+ } else {
location.hash = composeHash(location);
+ location.href = composeHref(location);
}
- location.href = composeHref(location);
+ update(location.href);
}
- update(location.href);
}
- /**
- * Update information about last location
- */
- function updateLastLocation() {
- lastLocationHref = location.href;
- lastLocationHash = location.hash;
- }
/**
* If location has changed, update the browser
* This method is called at the end of $eval() phase
*/
function updateBrowser() {
- updateLocation();
+ sync();
- if (location.href != lastLocationHref) {
- $browser.setUrl(lastBrowserUrl = location.href);
- updateLastLocation();
+ if ($browser.getUrl() != location.href) {
+ $browser.setUrl(location.href);
+ copy(location, lastLocation);
}
}