@@ -33,6 +33,7 @@ class RequestBuilder {
3333 fetchOptions . headers = {
3434 Accept : 'application/vnd.live-component+html' ,
3535 'X-Requested-With' : 'XMLHttpRequest' ,
36+ 'X-Live-Url' : window . location . pathname + window . location . search ,
3637 } ;
3738 const totalFiles = Object . entries ( files ) . reduce ( ( total , current ) => total + current . length , 0 ) ;
3839 const hasFingerprints = Object . keys ( children ) . length > 0 ;
@@ -111,6 +112,12 @@ class BackendResponse {
111112 }
112113 return this . body ;
113114 }
115+ getLiveUrl ( ) {
116+ if ( undefined === this . liveUrl ) {
117+ this . liveUrl = this . response . headers . get ( 'X-Live-Url' ) ;
118+ }
119+ return this . liveUrl ;
120+ }
114121}
115122
116123function getElementAsTagText ( element ) {
@@ -2146,6 +2153,10 @@ class Component {
21462153 return response ;
21472154 }
21482155 this . processRerender ( html , backendResponse ) ;
2156+ const liveUrl = backendResponse . getLiveUrl ( ) ;
2157+ if ( liveUrl ) {
2158+ history . replaceState ( history . state , '' , new URL ( liveUrl + window . location . hash , window . location . origin ) ) ;
2159+ }
21492160 this . backendRequest = null ;
21502161 thisPromiseResolve ( backendResponse ) ;
21512162 if ( this . isRequestPending ) {
@@ -2770,129 +2781,6 @@ class PollingPlugin {
27702781 }
27712782}
27722783
2773- function isValueEmpty ( value ) {
2774- if ( null === value || value === '' || undefined === value || ( Array . isArray ( value ) && value . length === 0 ) ) {
2775- return true ;
2776- }
2777- if ( typeof value !== 'object' ) {
2778- return false ;
2779- }
2780- for ( const key of Object . keys ( value ) ) {
2781- if ( ! isValueEmpty ( value [ key ] ) ) {
2782- return false ;
2783- }
2784- }
2785- return true ;
2786- }
2787- function toQueryString ( data ) {
2788- const buildQueryStringEntries = ( data , entries = { } , baseKey = '' ) => {
2789- Object . entries ( data ) . forEach ( ( [ iKey , iValue ] ) => {
2790- const key = baseKey === '' ? iKey : `${ baseKey } [${ iKey } ]` ;
2791- if ( '' === baseKey && isValueEmpty ( iValue ) ) {
2792- entries [ key ] = '' ;
2793- }
2794- else if ( null !== iValue ) {
2795- if ( typeof iValue === 'object' ) {
2796- entries = { ...entries , ...buildQueryStringEntries ( iValue , entries , key ) } ;
2797- }
2798- else {
2799- entries [ key ] = encodeURIComponent ( iValue )
2800- . replace ( / % 2 0 / g, '+' )
2801- . replace ( / % 2 C / g, ',' ) ;
2802- }
2803- }
2804- } ) ;
2805- return entries ;
2806- } ;
2807- const entries = buildQueryStringEntries ( data ) ;
2808- return Object . entries ( entries )
2809- . map ( ( [ key , value ] ) => `${ key } =${ value } ` )
2810- . join ( '&' ) ;
2811- }
2812- function fromQueryString ( search ) {
2813- search = search . replace ( '?' , '' ) ;
2814- if ( search === '' )
2815- return { } ;
2816- const insertDotNotatedValueIntoData = ( key , value , data ) => {
2817- const [ first , second , ...rest ] = key . split ( '.' ) ;
2818- if ( ! second ) {
2819- data [ key ] = value ;
2820- return value ;
2821- }
2822- if ( data [ first ] === undefined ) {
2823- data [ first ] = Number . isNaN ( Number . parseInt ( second ) ) ? { } : [ ] ;
2824- }
2825- insertDotNotatedValueIntoData ( [ second , ...rest ] . join ( '.' ) , value , data [ first ] ) ;
2826- } ;
2827- const entries = search . split ( '&' ) . map ( ( i ) => i . split ( '=' ) ) ;
2828- const data = { } ;
2829- entries . forEach ( ( [ key , value ] ) => {
2830- value = decodeURIComponent ( String ( value || '' ) . replace ( / \+ / g, '%20' ) ) ;
2831- if ( ! key . includes ( '[' ) ) {
2832- data [ key ] = value ;
2833- }
2834- else {
2835- if ( '' === value )
2836- return ;
2837- const dotNotatedKey = key . replace ( / \[ / g, '.' ) . replace ( / ] / g, '' ) ;
2838- insertDotNotatedValueIntoData ( dotNotatedKey , value , data ) ;
2839- }
2840- } ) ;
2841- return data ;
2842- }
2843- class UrlUtils extends URL {
2844- has ( key ) {
2845- const data = this . getData ( ) ;
2846- return Object . keys ( data ) . includes ( key ) ;
2847- }
2848- set ( key , value ) {
2849- const data = this . getData ( ) ;
2850- data [ key ] = value ;
2851- this . setData ( data ) ;
2852- }
2853- get ( key ) {
2854- return this . getData ( ) [ key ] ;
2855- }
2856- remove ( key ) {
2857- const data = this . getData ( ) ;
2858- delete data [ key ] ;
2859- this . setData ( data ) ;
2860- }
2861- getData ( ) {
2862- if ( ! this . search ) {
2863- return { } ;
2864- }
2865- return fromQueryString ( this . search ) ;
2866- }
2867- setData ( data ) {
2868- this . search = toQueryString ( data ) ;
2869- }
2870- }
2871- class HistoryStrategy {
2872- static replace ( url ) {
2873- history . replaceState ( history . state , '' , url ) ;
2874- }
2875- }
2876-
2877- class QueryStringPlugin {
2878- constructor ( mapping ) {
2879- this . mapping = mapping ;
2880- }
2881- attachToComponent ( component ) {
2882- component . on ( 'render:finished' , ( component ) => {
2883- const urlUtils = new UrlUtils ( window . location . href ) ;
2884- const currentUrl = urlUtils . toString ( ) ;
2885- Object . entries ( this . mapping ) . forEach ( ( [ prop , mapping ] ) => {
2886- const value = component . valueStore . get ( prop ) ;
2887- urlUtils . set ( mapping . name , value ) ;
2888- } ) ;
2889- if ( currentUrl !== urlUtils . toString ( ) ) {
2890- HistoryStrategy . replace ( urlUtils ) ;
2891- }
2892- } ) ;
2893- }
2894- }
2895-
28962784class SetValueOntoModelFieldsPlugin {
28972785 attachToComponent ( component ) {
28982786 this . synchronizeValueOfModelFields ( component ) ;
@@ -3102,7 +2990,6 @@ class LiveControllerDefault extends Controller {
31022990 new PageUnloadingPlugin ( ) ,
31032991 new PollingPlugin ( ) ,
31042992 new SetValueOntoModelFieldsPlugin ( ) ,
3105- new QueryStringPlugin ( this . queryMappingValue ) ,
31062993 new ChildComponentPlugin ( this . component ) ,
31072994 ] ;
31082995 plugins . forEach ( ( plugin ) => {
@@ -3233,7 +3120,6 @@ LiveControllerDefault.values = {
32333120 debounce : { type : Number , default : 150 } ,
32343121 fingerprint : { type : String , default : '' } ,
32353122 requestMethod : { type : String , default : 'post' } ,
3236- queryMapping : { type : Object , default : { } } ,
32373123} ;
32383124LiveControllerDefault . backendFactory = ( controller ) => new Backend ( controller . urlValue , controller . requestMethodValue ) ;
32393125
0 commit comments