1
+ /*can-route-pushstate@3.4.2#can-route-pushstate*/
2
+ define ( [
3
+ 'require' ,
4
+ 'exports' ,
5
+ 'module' ,
6
+ 'can-util/js/is-node' ,
7
+ 'can-util/js/assign' ,
8
+ 'can-util/js/each' ,
9
+ 'can-util/js/make-array' ,
10
+ 'can-util/js/diff-object' ,
11
+ 'can-util/namespace' ,
12
+ 'can-globals/location' ,
13
+ 'can-event' ,
14
+ 'can-route'
15
+ ] , function ( require , exports , module ) {
16
+ ( function ( global , require , exports , module ) {
17
+ 'use strict' ;
18
+ var isNode = require ( 'can-util/js/is-node' ) ;
19
+ var extend = require ( 'can-util/js/assign' ) ;
20
+ var each = require ( 'can-util/js/each' ) ;
21
+ var makeArray = require ( 'can-util/js/make-array' ) ;
22
+ var diffObject = require ( 'can-util/js/diff-object' ) ;
23
+ var namespace = require ( 'can-util/namespace' ) ;
24
+ var LOCATION = require ( 'can-globals/location' ) ;
25
+ var canEvent = require ( 'can-event' ) ;
26
+ var route = require ( 'can-route' ) ;
27
+ var hasPushstate = window . history && window . history . pushState ;
28
+ var loc = LOCATION ( ) ;
29
+ var validProtocols = {
30
+ 'http:' : true ,
31
+ 'https:' : true ,
32
+ '' : true
33
+ } ;
34
+ var usePushStateRouting = hasPushstate && loc && validProtocols [ loc . protocol ] ;
35
+ if ( usePushStateRouting ) {
36
+ route . bindings . pushstate = {
37
+ root : '/' ,
38
+ matchSlashes : false ,
39
+ paramsMatcher : / ^ \? (?: [ ^ = ] + = [ ^ & ] * & ) * [ ^ = ] + = [ ^ & ] * / ,
40
+ querySeparator : '?' ,
41
+ bind : function ( ) {
42
+ if ( isNode ( ) ) {
43
+ return ;
44
+ }
45
+ canEvent . on . call ( document . documentElement , 'click' , 'a' , anchorClickHandler ) ;
46
+ each ( methodsToOverwrite , function ( method ) {
47
+ originalMethods [ method ] = window . history [ method ] ;
48
+ window . history [ method ] = function ( state , title , url ) {
49
+ var absolute = url . indexOf ( 'http' ) === 0 ;
50
+ var loc = LOCATION ( ) ;
51
+ var searchHash = loc . search + loc . hash ;
52
+ if ( ! absolute && url !== loc . pathname + searchHash || absolute && url !== loc . href + searchHash ) {
53
+ originalMethods [ method ] . apply ( window . history , arguments ) ;
54
+ route . setState ( ) ;
55
+ }
56
+ } ;
57
+ } ) ;
58
+ canEvent . on . call ( window , 'popstate' , route . setState ) ;
59
+ } ,
60
+ unbind : function ( ) {
61
+ canEvent . off . call ( document . documentElement , 'click' , 'a' , anchorClickHandler ) ;
62
+ each ( methodsToOverwrite , function ( method ) {
63
+ window . history [ method ] = originalMethods [ method ] ;
64
+ } ) ;
65
+ canEvent . off . call ( window , 'popstate' , route . setState ) ;
66
+ } ,
67
+ matchingPartOfURL : function ( ) {
68
+ var root = cleanRoot ( ) , location = LOCATION ( ) , loc = location . pathname + location . search , index = loc . indexOf ( root ) ;
69
+ return loc . substr ( index + root . length ) ;
70
+ } ,
71
+ setURL : function ( path , newProps , oldProps ) {
72
+ var method = 'pushState' ;
73
+ var changed ;
74
+ if ( includeHash && path . indexOf ( '#' ) === - 1 && window . location . hash ) {
75
+ path += window . location . hash ;
76
+ }
77
+ changed = diffObject ( oldProps , newProps ) . map ( function ( d ) {
78
+ return d . property ;
79
+ } ) ;
80
+ if ( replaceStateAttrs . length > 0 ) {
81
+ var toRemove = [ ] ;
82
+ for ( var i = 0 , l = changed . length ; i < l ; i ++ ) {
83
+ if ( replaceStateAttrs . indexOf ( changed [ i ] ) !== - 1 ) {
84
+ method = 'replaceState' ;
85
+ }
86
+ if ( replaceStateAttrs . once && replaceStateAttrs . once . indexOf ( changed [ i ] ) !== - 1 ) {
87
+ toRemove . push ( changed [ i ] ) ;
88
+ }
89
+ }
90
+ if ( toRemove . length > 0 ) {
91
+ removeAttrs ( replaceStateAttrs , toRemove ) ;
92
+ removeAttrs ( replaceStateAttrs . once , toRemove ) ;
93
+ }
94
+ }
95
+ window . history [ method ] ( null , null , route . _call ( 'root' ) + path ) ;
96
+ }
97
+ } ;
98
+ var anchorClickHandler = function ( e ) {
99
+ if ( ! ( e . isDefaultPrevented ? e . isDefaultPrevented ( ) : e . defaultPrevented === true ) ) {
100
+ var node = this . _node || this ;
101
+ var linksHost = node . host || window . location . host ;
102
+ if ( node . href === 'javascript://' ) {
103
+ return ;
104
+ }
105
+ if ( node . target === '_blank' ) {
106
+ return ;
107
+ }
108
+ if ( e . altKey || e . ctrlKey || e . metaKey || e . shiftKey ) {
109
+ return ;
110
+ }
111
+ if ( window . location . host === linksHost ) {
112
+ var root = cleanRoot ( ) ;
113
+ if ( node . pathname . indexOf ( root ) === 0 ) {
114
+ var nodePathWithSearch = node . pathname + node . search ;
115
+ var url = nodePathWithSearch . substr ( root . length ) ;
116
+ var curParams = route . deparam ( url ) ;
117
+ if ( curParams . hasOwnProperty ( 'route' ) ) {
118
+ includeHash = true ;
119
+ var windowPathWithSearch = window . location . pathname + window . location . search ;
120
+ var shouldCallPreventDefault = nodePathWithSearch !== windowPathWithSearch || node . hash === window . location . hash ;
121
+ window . history . pushState ( null , null , node . href ) ;
122
+ if ( shouldCallPreventDefault && e . preventDefault ) {
123
+ e . preventDefault ( ) ;
124
+ }
125
+ }
126
+ }
127
+ }
128
+ }
129
+ } , cleanRoot = function ( ) {
130
+ var domain = location . protocol + '//' + location . host , root = route . _call ( 'root' ) , index = root . indexOf ( domain ) ;
131
+ if ( index === 0 ) {
132
+ return root . substr ( domain . length ) ;
133
+ }
134
+ return root ;
135
+ } , removeAttrs = function ( arr , attrs ) {
136
+ var index ;
137
+ for ( var i = attrs . length - 1 ; i >= 0 ; i -- ) {
138
+ if ( ( index = arr . indexOf ( attrs [ i ] ) ) !== - 1 ) {
139
+ arr . splice ( index , 1 ) ;
140
+ }
141
+ }
142
+ } , methodsToOverwrite = [
143
+ 'pushState' ,
144
+ 'replaceState'
145
+ ] , originalMethods = { } , includeHash = true , replaceStateAttrs = [ ] ;
146
+ route . defaultBinding = 'pushstate' ;
147
+ extend ( route , {
148
+ replaceStateOn : function ( ) {
149
+ var attrs = makeArray ( arguments ) ;
150
+ Array . prototype . push . apply ( replaceStateAttrs , attrs ) ;
151
+ } ,
152
+ replaceStateOnce : function ( ) {
153
+ var attrs = makeArray ( arguments ) ;
154
+ replaceStateAttrs . once = makeArray ( replaceStateAttrs . once ) ;
155
+ Array . prototype . push . apply ( replaceStateAttrs . once , attrs ) ;
156
+ route . replaceStateOn . apply ( this , arguments ) ;
157
+ } ,
158
+ replaceStateOff : function ( ) {
159
+ var attrs = makeArray ( arguments ) ;
160
+ removeAttrs ( replaceStateAttrs , attrs ) ;
161
+ }
162
+ } ) ;
163
+ }
164
+ module . exports = namespace . route = route ;
165
+ } ( function ( ) {
166
+ return this ;
167
+ } ( ) , require , exports , module ) ) ;
168
+ } ) ;
0 commit comments