@@ -303,9 +303,7 @@ function LocationHashbangInHtml5Url(appBase, hashPrefix) {
303
303
}
304
304
305
305
306
- LocationHashbangInHtml5Url . prototype =
307
- LocationHashbangUrl . prototype =
308
- LocationHtml5Url . prototype = {
306
+ var locationPrototype = {
309
307
310
308
/**
311
309
* Are we in html5 mode?
@@ -314,7 +312,7 @@ LocationHashbangInHtml5Url.prototype =
314
312
$$html5 : false ,
315
313
316
314
/**
317
- * Has any change been replacing ?
315
+ * Has any change been replacing?
318
316
* @private
319
317
*/
320
318
$$replace : false ,
@@ -530,6 +528,43 @@ LocationHashbangInHtml5Url.prototype =
530
528
}
531
529
} ;
532
530
531
+ forEach ( [ LocationHashbangInHtml5Url , LocationHashbangUrl , LocationHtml5Url ] , function ( Location ) {
532
+ Location . prototype = Object . create ( locationPrototype ) ;
533
+
534
+ /**
535
+ * @ngdoc method
536
+ * @name $location#state
537
+ *
538
+ * @description
539
+ * This method is getter / setter.
540
+ *
541
+ * Return the history state object when called without any parameter.
542
+ *
543
+ * Change the history state object when called with one parameter and return `$location`.
544
+ * The state object is later passed to `pushState` or `replaceState`.
545
+ *
546
+ * NOTE: This method is supported only in HTML5 mode and only in browsers supporting
547
+ * the HTML5 History API (i.e. methods `pushState` and `replaceState`). If you need to support
548
+ * older browsers (like IE9 or Android < 4.0), don't use this method.
549
+ *
550
+ * @param {object= } state State object for pushState or replaceState
551
+ * @return {object } state
552
+ */
553
+ Location . prototype . state = function ( state ) {
554
+ if ( ! arguments . length )
555
+ return this . $$state ;
556
+
557
+ if ( Location !== LocationHtml5Url || ! this . $$html5 ) {
558
+ throw $locationMinErr ( 'nostate' , 'History API state support is available only ' +
559
+ 'in HTML5 mode and only in browsers supporting HTML5 History API' ) ;
560
+ }
561
+ this . $$state = copy ( state ) ;
562
+
563
+ return this ;
564
+ } ;
565
+ } ) ;
566
+
567
+
533
568
function locationGetter ( property ) {
534
569
return function ( ) {
535
570
return this [ property ] ;
@@ -649,9 +684,14 @@ function $LocationProvider(){
649
684
* details about event object. Upon successful change
650
685
* {@link ng.$location#events_$locationChangeSuccess $locationChangeSuccess} is fired.
651
686
*
687
+ * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when
688
+ * the browser supports the HTML5 History API.
689
+ *
652
690
* @param {Object } angularEvent Synthetic event object.
653
691
* @param {string } newUrl New URL
654
692
* @param {string= } oldUrl URL that was before it was changed.
693
+ * @param {string= } newState New history state object
694
+ * @param {string= } oldState History state object that was before it was changed.
655
695
*/
656
696
657
697
/**
@@ -661,9 +701,14 @@ function $LocationProvider(){
661
701
* @description
662
702
* Broadcasted after a URL was changed.
663
703
*
704
+ * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when
705
+ * the browser supports the HTML5 History API.
706
+ *
664
707
* @param {Object } angularEvent Synthetic event object.
665
708
* @param {string } newUrl New URL
666
709
* @param {string= } oldUrl URL that was before it was changed.
710
+ * @param {string= } newState New history state object
711
+ * @param {string= } oldState History state object that was before it was changed.
667
712
*/
668
713
669
714
this . $get = [ '$rootScope' , '$browser' , '$sniffer' , '$rootElement' ,
@@ -687,6 +732,7 @@ function $LocationProvider(){
687
732
}
688
733
$location = new LocationMode ( appBase , '#' + hashPrefix ) ;
689
734
$location . $$parseLinkUrl ( initialUrl , initialUrl ) ;
735
+ $location . $$state = $browser . state ( ) ;
690
736
691
737
var IGNORE_URI_REGEXP = / ^ \s * ( j a v a s c r i p t | m a i l t o ) : / i;
692
738
@@ -741,18 +787,22 @@ function $LocationProvider(){
741
787
}
742
788
743
789
// update $location when $browser url changes
744
- $browser . onUrlChange ( function ( newUrl ) {
745
- if ( $location . absUrl ( ) != newUrl ) {
790
+ $browser . onUrlChange ( function ( newUrl , newState ) {
791
+ if ( $location . absUrl ( ) !== newUrl ||
792
+ ( $location . $$html5 && $location . state ( ) != newState && ! equals ( $location . state ( ) , newState ) ) ) {
746
793
$rootScope . $evalAsync ( function ( ) {
747
794
var oldUrl = $location . absUrl ( ) ;
795
+ var oldState = $location . state ( ) ;
748
796
749
797
$location . $$parse ( newUrl ) ;
750
- if ( $rootScope . $broadcast ( '$locationChangeStart' , newUrl ,
751
- oldUrl ) . defaultPrevented ) {
798
+ $location . $$state = copy ( newState ) ;
799
+ if ( $rootScope . $broadcast ( '$locationChangeStart' , newUrl , oldUrl ,
800
+ newState , oldState ) . defaultPrevented ) {
752
801
$location . $$parse ( oldUrl ) ;
753
- $browser . url ( oldUrl ) ;
802
+ $location . $$state = oldState ;
803
+ $browser . url ( $location . absUrl ( ) , false , newState ) ;
754
804
} else {
755
- afterLocationChange ( oldUrl ) ;
805
+ afterLocationChange ( oldUrl , oldState ) ;
756
806
}
757
807
} ) ;
758
808
if ( ! $rootScope . $$phase ) $rootScope . $digest ( ) ;
@@ -763,17 +813,20 @@ function $LocationProvider(){
763
813
var changeCounter = 0 ;
764
814
$rootScope . $watch ( function $locationWatch ( ) {
765
815
var oldUrl = $browser . url ( ) ;
816
+ var oldState = $browser . state ( ) ;
766
817
var currentReplace = $location . $$replace ;
767
818
768
- if ( ! changeCounter || oldUrl != $location . absUrl ( ) ) {
819
+ if ( ! changeCounter || oldUrl !== $location . absUrl ( ) ||
820
+ ( $location . $$html5 && oldState != $location . state ( ) && ! equals ( oldState , $location . state ( ) ) ) ) {
769
821
changeCounter ++ ;
770
822
$rootScope . $evalAsync ( function ( ) {
771
- if ( $rootScope . $broadcast ( '$locationChangeStart' , $location . absUrl ( ) , oldUrl ) .
772
- defaultPrevented ) {
823
+ if ( $rootScope . $broadcast ( '$locationChangeStart' , $location . absUrl ( ) , oldUrl ,
824
+ $location . state ( ) , oldState ) . defaultPrevented ) {
773
825
$location . $$parse ( oldUrl ) ;
826
+ $location . $$state = oldState ;
774
827
} else {
775
- $browser . url ( $location . absUrl ( ) , currentReplace ) ;
776
- afterLocationChange ( oldUrl ) ;
828
+ $browser . url ( $location . absUrl ( ) , currentReplace , $location . state ( ) ) ;
829
+ afterLocationChange ( oldUrl , oldState ) ;
777
830
}
778
831
} ) ;
779
832
}
@@ -784,8 +837,8 @@ function $LocationProvider(){
784
837
785
838
return $location ;
786
839
787
- function afterLocationChange ( oldUrl ) {
788
- $rootScope . $broadcast ( '$locationChangeSuccess' , $location . absUrl ( ) , oldUrl ) ;
840
+ function afterLocationChange ( oldUrl , oldState ) {
841
+ $rootScope . $broadcast ( '$locationChangeSuccess' , $location . absUrl ( ) , oldUrl , $location . state ( ) , oldState ) ;
789
842
}
790
843
} ] ;
791
844
}
0 commit comments