@@ -75,6 +75,7 @@ return (function () {
75
75
globalViewTransitions : false ,
76
76
methodsThatUseUrlParams : [ "get" ] ,
77
77
selfRequestsOnly : false ,
78
+ ignoreTitle : false ,
78
79
scrollIntoViewOnBoost : true
79
80
} ,
80
81
parseInterval :parseInterval ,
@@ -87,7 +88,7 @@ return (function () {
87
88
sock . binaryType = htmx . config . wsBinaryType ;
88
89
return sock ;
89
90
} ,
90
- version : "1.9.8 "
91
+ version : "1.9.9 "
91
92
} ;
92
93
93
94
/** @type {import("./htmx").HtmxInternalApi } */
@@ -1145,6 +1146,8 @@ return (function () {
1145
1146
var SYMBOL_CONT = / [ _ $ a - z A - Z 0 - 9 ] / ;
1146
1147
var STRINGISH_START = [ '"' , "'" , "/" ] ;
1147
1148
var NOT_WHITESPACE = / [ ^ \s ] / ;
1149
+ var COMBINED_SELECTOR_START = / [ { ( ] / ;
1150
+ var COMBINED_SELECTOR_END = / [ } ) ] / ;
1148
1151
function tokenizeString ( str ) {
1149
1152
var tokens = [ ] ;
1150
1153
var position = 0 ;
@@ -1233,6 +1236,18 @@ return (function () {
1233
1236
return result ;
1234
1237
}
1235
1238
1239
+ function consumeCSSSelector ( tokens ) {
1240
+ var result ;
1241
+ if ( tokens . length > 0 && COMBINED_SELECTOR_START . test ( tokens [ 0 ] ) ) {
1242
+ tokens . shift ( ) ;
1243
+ result = consumeUntil ( tokens , COMBINED_SELECTOR_END ) . trim ( ) ;
1244
+ tokens . shift ( ) ;
1245
+ } else {
1246
+ result = consumeUntil ( tokens , WHITESPACE_OR_COMMA ) ;
1247
+ }
1248
+ return result ;
1249
+ }
1250
+
1236
1251
var INPUT_SELECTOR = 'input, textarea, select' ;
1237
1252
1238
1253
/**
@@ -1281,29 +1296,33 @@ return (function () {
1281
1296
triggerSpec . delay = parseInterval ( consumeUntil ( tokens , WHITESPACE_OR_COMMA ) ) ;
1282
1297
} else if ( token === "from" && tokens [ 0 ] === ":" ) {
1283
1298
tokens . shift ( ) ;
1284
- var from_arg = consumeUntil ( tokens , WHITESPACE_OR_COMMA ) ;
1285
- if ( from_arg === "closest" || from_arg === "find" || from_arg === "next" || from_arg === "previous" ) {
1286
- tokens . shift ( ) ;
1287
- var selector = consumeUntil (
1288
- tokens ,
1289
- WHITESPACE_OR_COMMA
1290
- )
1291
- // `next` and `previous` allow a selector-less syntax
1292
- if ( selector . length > 0 ) {
1293
- from_arg += " " + selector ;
1299
+ if ( COMBINED_SELECTOR_START . test ( tokens [ 0 ] ) ) {
1300
+ var from_arg = consumeCSSSelector ( tokens ) ;
1301
+ } else {
1302
+ var from_arg = consumeUntil ( tokens , WHITESPACE_OR_COMMA ) ;
1303
+ if ( from_arg === "closest" || from_arg === "find" || from_arg === "next" || from_arg === "previous" ) {
1304
+ tokens . shift ( ) ;
1305
+ var selector = consumeCSSSelector ( tokens ) ;
1306
+ // `next` and `previous` allow a selector-less syntax
1307
+ if ( selector . length > 0 ) {
1308
+ from_arg += " " + selector ;
1309
+ }
1294
1310
}
1295
1311
}
1296
1312
triggerSpec . from = from_arg ;
1297
1313
} else if ( token === "target" && tokens [ 0 ] === ":" ) {
1298
1314
tokens . shift ( ) ;
1299
- triggerSpec . target = consumeUntil ( tokens , WHITESPACE_OR_COMMA ) ;
1315
+ triggerSpec . target = consumeCSSSelector ( tokens ) ;
1300
1316
} else if ( token === "throttle" && tokens [ 0 ] === ":" ) {
1301
1317
tokens . shift ( ) ;
1302
1318
triggerSpec . throttle = parseInterval ( consumeUntil ( tokens , WHITESPACE_OR_COMMA ) ) ;
1303
1319
} else if ( token === "queue" && tokens [ 0 ] === ":" ) {
1304
1320
tokens . shift ( ) ;
1305
1321
triggerSpec . queue = consumeUntil ( tokens , WHITESPACE_OR_COMMA ) ;
1306
- } else if ( ( token === "root" || token === "threshold" ) && tokens [ 0 ] === ":" ) {
1322
+ } else if ( token === "root" && tokens [ 0 ] === ":" ) {
1323
+ tokens . shift ( ) ;
1324
+ triggerSpec [ token ] = consumeCSSSelector ( tokens ) ;
1325
+ } else if ( token === "threshold" && tokens [ 0 ] === ":" ) {
1307
1326
tokens . shift ( ) ;
1308
1327
triggerSpec [ token ] = consumeUntil ( tokens , WHITESPACE_OR_COMMA ) ;
1309
1328
} else {
@@ -2906,6 +2925,7 @@ return (function () {
2906
2925
values : context . values ,
2907
2926
targetOverride : resolveTarget ( context . target ) ,
2908
2927
swapOverride : context . swap ,
2928
+ select : context . select ,
2909
2929
returnPromise : true
2910
2930
} ) ;
2911
2931
}
@@ -2960,6 +2980,7 @@ return (function () {
2960
2980
elt = getDocument ( ) . body ;
2961
2981
}
2962
2982
var responseHandler = etc . handler || handleAjaxResponse ;
2983
+ var select = etc . select || null ;
2963
2984
2964
2985
if ( ! bodyContains ( elt ) ) {
2965
2986
// do not issue requests for elements removed from the DOM
@@ -3108,6 +3129,11 @@ return (function () {
3108
3129
3109
3130
3110
3131
var headers = getHeaders ( elt , target , promptResponse ) ;
3132
+
3133
+ if ( verb !== 'get' && ! usesFormData ( elt ) ) {
3134
+ headers [ 'Content-Type' ] = 'application/x-www-form-urlencoded' ;
3135
+ }
3136
+
3111
3137
if ( etc . headers ) {
3112
3138
headers = mergeObjects ( headers , etc . headers ) ;
3113
3139
}
@@ -3121,10 +3147,6 @@ return (function () {
3121
3147
var allParameters = mergeObjects ( rawParameters , expressionVars ) ;
3122
3148
var filteredParameters = filterValues ( allParameters , elt ) ;
3123
3149
3124
- if ( verb !== 'get' && ! usesFormData ( elt ) ) {
3125
- headers [ 'Content-Type' ] = 'application/x-www-form-urlencoded' ;
3126
- }
3127
-
3128
3150
if ( htmx . config . getCacheBusterParam && verb === 'get' ) {
3129
3151
filteredParameters [ 'org.htmx.cache-buster' ] = getRawAttribute ( target , "id" ) || "true" ;
3130
3152
}
@@ -3222,7 +3244,7 @@ return (function () {
3222
3244
}
3223
3245
3224
3246
var responseInfo = {
3225
- xhr : xhr , target : target , requestConfig : requestConfig , etc : etc , boosted : eltIsBoosted ,
3247
+ xhr : xhr , target : target , requestConfig : requestConfig , etc : etc , boosted : eltIsBoosted , select : select ,
3226
3248
pathInfo : {
3227
3249
requestPath : path ,
3228
3250
finalRequestPath : finalPath ,
@@ -3393,6 +3415,7 @@ return (function () {
3393
3415
var target = responseInfo . target ;
3394
3416
var etc = responseInfo . etc ;
3395
3417
var requestConfig = responseInfo . requestConfig ;
3418
+ var select = responseInfo . select ;
3396
3419
3397
3420
if ( ! triggerEvent ( elt , 'htmx:beforeOnLoad' , responseInfo ) ) return ;
3398
3421
@@ -3502,10 +3525,26 @@ return (function () {
3502
3525
}
3503
3526
3504
3527
var selectOverride ;
3528
+ if ( select ) {
3529
+ selectOverride = select ;
3530
+ }
3531
+
3505
3532
if ( hasHeader ( xhr , / H X - R e s e l e c t : / i) ) {
3506
3533
selectOverride = xhr . getResponseHeader ( "HX-Reselect" ) ;
3507
3534
}
3508
3535
3536
+ // if we need to save history, do so, before swapping so that relative resources have the correct base URL
3537
+ if ( historyUpdate . type ) {
3538
+ triggerEvent ( getDocument ( ) . body , 'htmx:beforeHistoryUpdate' , mergeObjects ( { history : historyUpdate } , responseInfo ) ) ;
3539
+ if ( historyUpdate . type === "push" ) {
3540
+ pushUrlIntoHistory ( historyUpdate . path ) ;
3541
+ triggerEvent ( getDocument ( ) . body , 'htmx:pushedIntoHistory' , { path : historyUpdate . path } ) ;
3542
+ } else {
3543
+ replaceUrlInHistory ( historyUpdate . path ) ;
3544
+ triggerEvent ( getDocument ( ) . body , 'htmx:replacedInHistory' , { path : historyUpdate . path } ) ;
3545
+ }
3546
+ }
3547
+
3509
3548
var settleInfo = makeSettleInfo ( target ) ;
3510
3549
selectAndSwap ( swapSpec . swapStyle , target , elt , serverResponse , settleInfo , selectOverride ) ;
3511
3550
@@ -3555,17 +3594,6 @@ return (function () {
3555
3594
triggerEvent ( elt , 'htmx:afterSettle' , responseInfo ) ;
3556
3595
} ) ;
3557
3596
3558
- // if we need to save history, do so
3559
- if ( historyUpdate . type ) {
3560
- triggerEvent ( getDocument ( ) . body , 'htmx:beforeHistoryUpdate' , mergeObjects ( { history : historyUpdate } , responseInfo ) ) ;
3561
- if ( historyUpdate . type === "push" ) {
3562
- pushUrlIntoHistory ( historyUpdate . path ) ;
3563
- triggerEvent ( getDocument ( ) . body , 'htmx:pushedIntoHistory' , { path : historyUpdate . path } ) ;
3564
- } else {
3565
- replaceUrlInHistory ( historyUpdate . path ) ;
3566
- triggerEvent ( getDocument ( ) . body , 'htmx:replacedInHistory' , { path : historyUpdate . path } ) ;
3567
- }
3568
- }
3569
3597
if ( responseInfo . pathInfo . anchor ) {
3570
3598
var anchorTarget = getDocument ( ) . getElementById ( responseInfo . pathInfo . anchor ) ;
3571
3599
if ( anchorTarget ) {
@@ -3724,35 +3752,44 @@ return (function () {
3724
3752
//====================================================================
3725
3753
// Initialization
3726
3754
//====================================================================
3727
- var isReady = false
3728
- getDocument ( ) . addEventListener ( 'DOMContentLoaded' , function ( ) {
3729
- isReady = true
3730
- } )
3731
-
3732
3755
/**
3733
- * Execute a function now if DOMContentLoaded has fired, otherwise listen for it.
3734
- *
3735
- * This function uses isReady because there is no realiable way to ask the browswer whether
3736
- * the DOMContentLoaded event has already been fired; there's a gap between DOMContentLoaded
3737
- * firing and readystate=complete.
3756
+ * We want to initialize the page elements after DOMContentLoaded
3757
+ * fires, but there isn't always a good way to tell whether
3758
+ * it has already fired when we get here or not.
3738
3759
*/
3739
- function ready ( fn ) {
3740
- // Checking readyState here is a failsafe in case the htmx script tag entered the DOM by
3741
- // some means other than the initial page load.
3742
- if ( isReady || getDocument ( ) . readyState === 'complete' ) {
3743
- fn ( ) ;
3744
- } else {
3745
- getDocument ( ) . addEventListener ( 'DOMContentLoaded' , fn ) ;
3760
+ function ready ( functionToCall ) {
3761
+ // call the function exactly once no matter how many times this is called
3762
+ var callReadyFunction = function ( ) {
3763
+ if ( ! functionToCall ) return ;
3764
+ functionToCall ( ) ;
3765
+ functionToCall = null ;
3766
+ } ;
3767
+
3768
+ if ( getDocument ( ) . readyState === "complete" ) {
3769
+ // DOMContentLoaded definitely fired, we can initialize the page
3770
+ callReadyFunction ( ) ;
3771
+ }
3772
+ else {
3773
+ /* DOMContentLoaded *maybe* already fired, wait for
3774
+ * the next DOMContentLoaded or readystatechange event
3775
+ */
3776
+ getDocument ( ) . addEventListener ( "DOMContentLoaded" , function ( ) {
3777
+ callReadyFunction ( ) ;
3778
+ } ) ;
3779
+ getDocument ( ) . addEventListener ( "readystatechange" , function ( ) {
3780
+ if ( getDocument ( ) . readyState !== "complete" ) return ;
3781
+ callReadyFunction ( ) ;
3782
+ } ) ;
3746
3783
}
3747
3784
}
3748
3785
3749
3786
function insertIndicatorStyles ( ) {
3750
3787
if ( htmx . config . includeIndicatorStyles !== false ) {
3751
3788
getDocument ( ) . head . insertAdjacentHTML ( "beforeend" ,
3752
3789
"<style>\
3753
- ." + htmx . config . indicatorClass + "{opacity:0;transition: opacity 200ms ease-in; }\
3754
- ." + htmx . config . requestClass + " ." + htmx . config . indicatorClass + "{opacity:1}\
3755
- ." + htmx . config . requestClass + "." + htmx . config . indicatorClass + "{opacity:1}\
3790
+ ." + htmx . config . indicatorClass + "{opacity:0}\
3791
+ ." + htmx . config . requestClass + " ." + htmx . config . indicatorClass + "{opacity:1; transition: opacity 200ms ease-in; }\
3792
+ ." + htmx . config . requestClass + "." + htmx . config . indicatorClass + "{opacity:1; transition: opacity 200ms ease-in; }\
3756
3793
</style>" ) ;
3757
3794
}
3758
3795
}
0 commit comments