htmx.org 2.0.3 → 2.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/htmx.cjs.js CHANGED
@@ -277,7 +277,7 @@ var htmx = (function() {
277
277
  parseInterval: null,
278
278
  /** @type {typeof internalEval} */
279
279
  _: null,
280
- version: '2.0.3'
280
+ version: '2.0.4'
281
281
  }
282
282
  // Tsc madness part 2
283
283
  htmx.onLoad = onLoadHelper
@@ -693,6 +693,7 @@ var htmx = (function() {
693
693
  * @property {XMLHttpRequest} [xhr]
694
694
  * @property {(() => void)[]} [queuedRequests]
695
695
  * @property {boolean} [abortable]
696
+ * @property {boolean} [firstInitCompleted]
696
697
  *
697
698
  * Event data
698
699
  * @property {HtmxTriggerSpecification} [triggerSpec]
@@ -754,17 +755,14 @@ var htmx = (function() {
754
755
  }
755
756
 
756
757
  /**
758
+ * Checks whether the element is in the document (includes shadow roots).
759
+ * This function this is a slight misnomer; it will return true even for elements in the head.
760
+ *
757
761
  * @param {Node} elt
758
762
  * @returns {boolean}
759
763
  */
760
764
  function bodyContains(elt) {
761
- // IE Fix
762
- const rootNode = elt.getRootNode && elt.getRootNode()
763
- if (rootNode && rootNode instanceof window.ShadowRoot) {
764
- return getDocument().body.contains(rootNode.host)
765
- } else {
766
- return getDocument().body.contains(elt)
767
- }
765
+ return elt.getRootNode({ composed: true }) === document
768
766
  }
769
767
 
770
768
  /**
@@ -1128,34 +1126,77 @@ var htmx = (function() {
1128
1126
  * @returns {(Node|Window)[]}
1129
1127
  */
1130
1128
  function querySelectorAllExt(elt, selector, global) {
1131
- elt = resolveTarget(elt)
1132
- if (selector.indexOf('closest ') === 0) {
1133
- return [closest(asElement(elt), normalizeSelector(selector.substr(8)))]
1134
- } else if (selector.indexOf('find ') === 0) {
1135
- return [find(asParentNode(elt), normalizeSelector(selector.substr(5)))]
1136
- } else if (selector === 'next') {
1137
- return [asElement(elt).nextElementSibling]
1138
- } else if (selector.indexOf('next ') === 0) {
1139
- return [scanForwardQuery(elt, normalizeSelector(selector.substr(5)), !!global)]
1140
- } else if (selector === 'previous') {
1141
- return [asElement(elt).previousElementSibling]
1142
- } else if (selector.indexOf('previous ') === 0) {
1143
- return [scanBackwardsQuery(elt, normalizeSelector(selector.substr(9)), !!global)]
1144
- } else if (selector === 'document') {
1145
- return [document]
1146
- } else if (selector === 'window') {
1147
- return [window]
1148
- } else if (selector === 'body') {
1149
- return [document.body]
1150
- } else if (selector === 'root') {
1151
- return [getRootNode(elt, !!global)]
1152
- } else if (selector === 'host') {
1153
- return [(/** @type ShadowRoot */(elt.getRootNode())).host]
1154
- } else if (selector.indexOf('global ') === 0) {
1129
+ if (selector.indexOf('global ') === 0) {
1155
1130
  return querySelectorAllExt(elt, selector.slice(7), true)
1156
- } else {
1157
- return toArray(asParentNode(getRootNode(elt, !!global)).querySelectorAll(normalizeSelector(selector)))
1158
1131
  }
1132
+
1133
+ elt = resolveTarget(elt)
1134
+
1135
+ const parts = []
1136
+ {
1137
+ let chevronsCount = 0
1138
+ let offset = 0
1139
+ for (let i = 0; i < selector.length; i++) {
1140
+ const char = selector[i]
1141
+ if (char === ',' && chevronsCount === 0) {
1142
+ parts.push(selector.substring(offset, i))
1143
+ offset = i + 1
1144
+ continue
1145
+ }
1146
+ if (char === '<') {
1147
+ chevronsCount++
1148
+ } else if (char === '/' && i < selector.length - 1 && selector[i + 1] === '>') {
1149
+ chevronsCount--
1150
+ }
1151
+ }
1152
+ if (offset < selector.length) {
1153
+ parts.push(selector.substring(offset))
1154
+ }
1155
+ }
1156
+
1157
+ const result = []
1158
+ const unprocessedParts = []
1159
+ while (parts.length > 0) {
1160
+ const selector = normalizeSelector(parts.shift())
1161
+ let item
1162
+ if (selector.indexOf('closest ') === 0) {
1163
+ item = closest(asElement(elt), normalizeSelector(selector.substr(8)))
1164
+ } else if (selector.indexOf('find ') === 0) {
1165
+ item = find(asParentNode(elt), normalizeSelector(selector.substr(5)))
1166
+ } else if (selector === 'next' || selector === 'nextElementSibling') {
1167
+ item = asElement(elt).nextElementSibling
1168
+ } else if (selector.indexOf('next ') === 0) {
1169
+ item = scanForwardQuery(elt, normalizeSelector(selector.substr(5)), !!global)
1170
+ } else if (selector === 'previous' || selector === 'previousElementSibling') {
1171
+ item = asElement(elt).previousElementSibling
1172
+ } else if (selector.indexOf('previous ') === 0) {
1173
+ item = scanBackwardsQuery(elt, normalizeSelector(selector.substr(9)), !!global)
1174
+ } else if (selector === 'document') {
1175
+ item = document
1176
+ } else if (selector === 'window') {
1177
+ item = window
1178
+ } else if (selector === 'body') {
1179
+ item = document.body
1180
+ } else if (selector === 'root') {
1181
+ item = getRootNode(elt, !!global)
1182
+ } else if (selector === 'host') {
1183
+ item = (/** @type ShadowRoot */(elt.getRootNode())).host
1184
+ } else {
1185
+ unprocessedParts.push(selector)
1186
+ }
1187
+
1188
+ if (item) {
1189
+ result.push(item)
1190
+ }
1191
+ }
1192
+
1193
+ if (unprocessedParts.length > 0) {
1194
+ const standardSelector = unprocessedParts.join(',')
1195
+ const rootNode = asParentNode(getRootNode(elt, !!global))
1196
+ result.push(...toArray(rootNode.querySelectorAll(standardSelector)))
1197
+ }
1198
+
1199
+ return result
1159
1200
  }
1160
1201
 
1161
1202
  /**
@@ -1418,8 +1459,8 @@ var htmx = (function() {
1418
1459
  if (oobValue === 'true') {
1419
1460
  // do nothing
1420
1461
  } else if (oobValue.indexOf(':') > 0) {
1421
- swapStyle = oobValue.substr(0, oobValue.indexOf(':'))
1422
- selector = oobValue.substr(oobValue.indexOf(':') + 1, oobValue.length)
1462
+ swapStyle = oobValue.substring(0, oobValue.indexOf(':'))
1463
+ selector = oobValue.substring(oobValue.indexOf(':') + 1)
1423
1464
  } else {
1424
1465
  swapStyle = oobValue
1425
1466
  }
@@ -1628,7 +1669,7 @@ var htmx = (function() {
1628
1669
  })
1629
1670
  }
1630
1671
  deInitOnHandlers(element)
1631
- forEach(Object.keys(internalData), function(key) { delete internalData[key] })
1672
+ forEach(Object.keys(internalData), function(key) { if (key !== 'firstInitCompleted') delete internalData[key] })
1632
1673
  }
1633
1674
 
1634
1675
  /**
@@ -1889,7 +1930,7 @@ var htmx = (function() {
1889
1930
  // oob swaps
1890
1931
  findAndSwapOobElements(fragment, settleInfo, rootNode)
1891
1932
  forEach(findAll(fragment, 'template'), /** @param {HTMLTemplateElement} template */function(template) {
1892
- if (findAndSwapOobElements(template.content, settleInfo, rootNode)) {
1933
+ if (template.content && findAndSwapOobElements(template.content, settleInfo, rootNode)) {
1893
1934
  // Avoid polluting the DOM with empty templates that were only used to encapsulate oob swap
1894
1935
  template.remove()
1895
1936
  }
@@ -2028,7 +2069,7 @@ var htmx = (function() {
2028
2069
  while (SYMBOL_CONT.exec(str.charAt(position + 1))) {
2029
2070
  position++
2030
2071
  }
2031
- tokens.push(str.substr(startPosition, position - startPosition + 1))
2072
+ tokens.push(str.substring(startPosition, position + 1))
2032
2073
  } else if (STRINGISH_START.indexOf(str.charAt(position)) !== -1) {
2033
2074
  const startChar = str.charAt(position)
2034
2075
  var startPosition = position
@@ -2039,7 +2080,7 @@ var htmx = (function() {
2039
2080
  }
2040
2081
  position++
2041
2082
  }
2042
- tokens.push(str.substr(startPosition, position - startPosition + 1))
2083
+ tokens.push(str.substring(startPosition, position + 1))
2043
2084
  } else {
2044
2085
  const symbol = str.charAt(position)
2045
2086
  tokens.push(symbol)
@@ -2323,6 +2364,11 @@ var htmx = (function() {
2323
2364
  const rawAttribute = getRawAttribute(elt, 'method')
2324
2365
  verb = (/** @type HttpVerb */(rawAttribute ? rawAttribute.toLowerCase() : 'get'))
2325
2366
  path = getRawAttribute(elt, 'action')
2367
+ if (path == null || path === '') {
2368
+ // if there is no action attribute on the form set path to current href before the
2369
+ // following logic to properly clear parameters on a GET (not on a POST!)
2370
+ path = getDocument().location.href
2371
+ }
2326
2372
  if (verb === 'get' && path.includes('?')) {
2327
2373
  path = path.replace(/\?[^#]+/, '')
2328
2374
  }
@@ -2354,7 +2400,8 @@ var htmx = (function() {
2354
2400
  if (elt.tagName === 'FORM') {
2355
2401
  return true
2356
2402
  }
2357
- if (matches(elt, 'input[type="submit"], button') && closest(elt, 'form') !== null) {
2403
+ if (matches(elt, 'input[type="submit"], button') &&
2404
+ (matches(elt, '[form]') || closest(elt, 'form') !== null)) {
2358
2405
  return true
2359
2406
  }
2360
2407
  if (elt instanceof HTMLAnchorElement && elt.href &&
@@ -2559,6 +2606,7 @@ var htmx = (function() {
2559
2606
  const load = function() {
2560
2607
  if (!nodeData.loaded) {
2561
2608
  nodeData.loaded = true
2609
+ triggerEvent(elt, 'htmx:trigger')
2562
2610
  handler(elt)
2563
2611
  }
2564
2612
  }
@@ -2634,7 +2682,7 @@ var htmx = (function() {
2634
2682
  }, observerOptions)
2635
2683
  observer.observe(asElement(elt))
2636
2684
  addEventListener(asElement(elt), handler, nodeData, triggerSpec)
2637
- } else if (triggerSpec.trigger === 'load') {
2685
+ } else if (!nodeData.firstInitCompleted && triggerSpec.trigger === 'load') {
2638
2686
  if (!maybeFilterEvent(triggerSpec, elt, makeEvent('load', { elt }))) {
2639
2687
  loadImmediately(asElement(elt), handler, nodeData, triggerSpec.delay)
2640
2688
  }
@@ -2841,11 +2889,12 @@ var htmx = (function() {
2841
2889
  return
2842
2890
  }
2843
2891
  const nodeData = getInternalData(elt)
2844
- if (nodeData.initHash !== attributeHash(elt)) {
2892
+ const attrHash = attributeHash(elt)
2893
+ if (nodeData.initHash !== attrHash) {
2845
2894
  // clean up any previously processed info
2846
2895
  deInitNode(elt)
2847
2896
 
2848
- nodeData.initHash = attributeHash(elt)
2897
+ nodeData.initHash = attrHash
2849
2898
 
2850
2899
  triggerEvent(elt, 'htmx:beforeProcessNode')
2851
2900
 
@@ -2870,6 +2919,7 @@ var htmx = (function() {
2870
2919
  initButtonTracking(elt)
2871
2920
  }
2872
2921
 
2922
+ nodeData.firstInitCompleted = true
2873
2923
  triggerEvent(elt, 'htmx:afterProcessNode')
2874
2924
  }
2875
2925
  }
@@ -3581,7 +3631,7 @@ var htmx = (function() {
3581
3631
  } else if (paramsValue === '*') {
3582
3632
  return inputValues
3583
3633
  } else if (paramsValue.indexOf('not ') === 0) {
3584
- forEach(paramsValue.substr(4).split(','), function(name) {
3634
+ forEach(paramsValue.slice(4).split(','), function(name) {
3585
3635
  name = name.trim()
3586
3636
  inputValues.delete(name)
3587
3637
  })
@@ -3631,15 +3681,15 @@ var htmx = (function() {
3631
3681
  for (let i = 0; i < split.length; i++) {
3632
3682
  const value = split[i]
3633
3683
  if (value.indexOf('swap:') === 0) {
3634
- swapSpec.swapDelay = parseInterval(value.substr(5))
3684
+ swapSpec.swapDelay = parseInterval(value.slice(5))
3635
3685
  } else if (value.indexOf('settle:') === 0) {
3636
- swapSpec.settleDelay = parseInterval(value.substr(7))
3686
+ swapSpec.settleDelay = parseInterval(value.slice(7))
3637
3687
  } else if (value.indexOf('transition:') === 0) {
3638
- swapSpec.transition = value.substr(11) === 'true'
3688
+ swapSpec.transition = value.slice(11) === 'true'
3639
3689
  } else if (value.indexOf('ignoreTitle:') === 0) {
3640
- swapSpec.ignoreTitle = value.substr(12) === 'true'
3690
+ swapSpec.ignoreTitle = value.slice(12) === 'true'
3641
3691
  } else if (value.indexOf('scroll:') === 0) {
3642
- const scrollSpec = value.substr(7)
3692
+ const scrollSpec = value.slice(7)
3643
3693
  var splitSpec = scrollSpec.split(':')
3644
3694
  const scrollVal = splitSpec.pop()
3645
3695
  var selectorVal = splitSpec.length > 0 ? splitSpec.join(':') : null
@@ -3647,14 +3697,14 @@ var htmx = (function() {
3647
3697
  swapSpec.scroll = scrollVal
3648
3698
  swapSpec.scrollTarget = selectorVal
3649
3699
  } else if (value.indexOf('show:') === 0) {
3650
- const showSpec = value.substr(5)
3700
+ const showSpec = value.slice(5)
3651
3701
  var splitSpec = showSpec.split(':')
3652
3702
  const showVal = splitSpec.pop()
3653
3703
  var selectorVal = splitSpec.length > 0 ? splitSpec.join(':') : null
3654
3704
  swapSpec.show = showVal
3655
3705
  swapSpec.showTarget = selectorVal
3656
3706
  } else if (value.indexOf('focus-scroll:') === 0) {
3657
- const focusScrollVal = value.substr('focus-scroll:'.length)
3707
+ const focusScrollVal = value.slice('focus-scroll:'.length)
3658
3708
  swapSpec.focusScroll = focusScrollVal == 'true'
3659
3709
  } else if (i == 0) {
3660
3710
  swapSpec.swapStyle = value
@@ -3776,10 +3826,10 @@ var htmx = (function() {
3776
3826
  return null
3777
3827
  }
3778
3828
  if (str.indexOf('javascript:') === 0) {
3779
- str = str.substr(11)
3829
+ str = str.slice(11)
3780
3830
  evaluateValue = true
3781
3831
  } else if (str.indexOf('js:') === 0) {
3782
- str = str.substr(3)
3832
+ str = str.slice(3)
3783
3833
  evaluateValue = true
3784
3834
  }
3785
3835
  if (str.indexOf('{') !== 0) {
@@ -3905,9 +3955,9 @@ var htmx = (function() {
3905
3955
  })
3906
3956
  } else {
3907
3957
  let resolvedTarget = resolveTarget(context.target)
3908
- // If target is supplied but can't resolve OR both target and source can't be resolved
3958
+ // If target is supplied but can't resolve OR source is supplied but both target and source can't be resolved
3909
3959
  // then use DUMMY_ELT to abort the request with htmx:targetError to avoid it replacing body by mistake
3910
- if ((context.target && !resolvedTarget) || (!resolvedTarget && !resolveTarget(context.source))) {
3960
+ if ((context.target && !resolvedTarget) || (context.source && !resolvedTarget && !resolveTarget(context.source))) {
3911
3961
  resolvedTarget = DUMMY_ELT
3912
3962
  }
3913
3963
  return issueAjaxRequest(verb, path, resolveTarget(context.source), context.event,
@@ -4039,7 +4089,15 @@ var htmx = (function() {
4039
4089
  get: function(target, name) {
4040
4090
  if (typeof name === 'symbol') {
4041
4091
  // Forward symbol calls to the FormData itself directly
4042
- return Reflect.get(target, name)
4092
+ const result = Reflect.get(target, name)
4093
+ // Wrap in function with apply to correctly bind the FormData context, as a direct call would result in an illegal invocation error
4094
+ if (typeof result === 'function') {
4095
+ return function() {
4096
+ return result.apply(formData, arguments)
4097
+ }
4098
+ } else {
4099
+ return result
4100
+ }
4043
4101
  }
4044
4102
  if (name === 'toJSON') {
4045
4103
  // Support JSON.stringify call on proxy
@@ -4873,7 +4931,7 @@ var htmx = (function() {
4873
4931
  * @see https://htmx.org/api/#defineExtension
4874
4932
  *
4875
4933
  * @param {string} name the extension name
4876
- * @param {HtmxExtension} extension the extension definition
4934
+ * @param {Partial<HtmxExtension>} extension the extension definition
4877
4935
  */
4878
4936
  function defineExtension(name, extension) {
4879
4937
  if (extension.init) {
@@ -159,7 +159,7 @@ declare namespace htmx {
159
159
  let toggleClass: (elt: Element | string, clazz: string) => void;
160
160
  let takeClass: (elt: Node | string, clazz: string) => void;
161
161
  let swap: (target: string | Element, content: string, swapSpec: HtmxSwapSpecification, swapOptions?: SwapOptions) => void;
162
- let defineExtension: (name: string, extension: HtmxExtension) => void;
162
+ let defineExtension: (name: string, extension: Partial<HtmxExtension>) => void;
163
163
  let removeExtension: (name: string) => void;
164
164
  let logAll: () => void;
165
165
  let logNone: () => void;