Skip to content

Commit 609e23f

Browse files
committed
Fix indenting and add tests
1 parent 010e98a commit 609e23f

3 files changed

Lines changed: 181 additions & 157 deletions

File tree

src/htmx.js

Lines changed: 153 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -1866,134 +1866,134 @@ var htmx = (function() {
18661866
let settleResolve = null
18671867
let settleReject = null
18681868

1869-
let localSwap = function() {
1870-
maybeCall(swapOptions.beforeSwapCallback)
1871-
1872-
target = resolveTarget(target)
1873-
const rootNode = swapOptions.contextElement ? getRootNode(swapOptions.contextElement, false) : getDocument()
1874-
1875-
// preserve focus and selection
1876-
const activeElt = document.activeElement
1877-
let selectionInfo = {}
1878-
selectionInfo = {
1879-
elt: activeElt,
1880-
// @ts-ignore
1881-
start: activeElt ? activeElt.selectionStart : null,
1882-
// @ts-ignore
1883-
end: activeElt ? activeElt.selectionEnd : null
1884-
}
1885-
const settleInfo = makeSettleInfo(target)
1886-
1887-
// For text content swaps, don't parse the response as HTML, just insert it
1888-
if (swapSpec.swapStyle === 'textContent') {
1889-
target.textContent = content
1890-
// Otherwise, make the fragment and process it
1891-
} else {
1892-
let fragment = makeFragment(content)
1893-
1894-
settleInfo.title = fragment.title
1895-
1896-
// select-oob swaps
1897-
if (swapOptions.selectOOB) {
1898-
const oobSelectValues = swapOptions.selectOOB.split(',')
1899-
for (let i = 0; i < oobSelectValues.length; i++) {
1900-
const oobSelectValue = oobSelectValues[i].split(':', 2)
1901-
let id = oobSelectValue[0].trim()
1902-
if (id.indexOf('#') === 0) {
1903-
id = id.substring(1)
1904-
}
1905-
const oobValue = oobSelectValue[1] || 'true'
1906-
const oobElement = fragment.querySelector('#' + id)
1907-
if (oobElement) {
1908-
oobSwap(oobValue, oobElement, settleInfo, rootNode)
1909-
}
1910-
}
1911-
}
1912-
// oob swaps
1913-
findAndSwapOobElements(fragment, settleInfo, rootNode)
1914-
forEach(findAll(fragment, 'template'), /** @param {HTMLTemplateElement} template */function(template) {
1915-
if (template.content && findAndSwapOobElements(template.content, settleInfo, rootNode)) {
1916-
// Avoid polluting the DOM with empty templates that were only used to encapsulate oob swap
1917-
template.remove()
1918-
}
1919-
})
1869+
let doSwap = function() {
1870+
maybeCall(swapOptions.beforeSwapCallback)
19201871

1921-
// normal swap
1922-
if (swapOptions.select) {
1923-
const newFragment = getDocument().createDocumentFragment()
1924-
forEach(fragment.querySelectorAll(swapOptions.select), function(node) {
1925-
newFragment.appendChild(node)
1926-
})
1927-
fragment = newFragment
1928-
}
1929-
handlePreservedElements(fragment)
1930-
swapWithStyle(swapSpec.swapStyle, swapOptions.contextElement, target, fragment, settleInfo)
1931-
restorePreservedElements()
1932-
}
1872+
target = resolveTarget(target)
1873+
const rootNode = swapOptions.contextElement ? getRootNode(swapOptions.contextElement, false) : getDocument()
19331874

1934-
// apply saved focus and selection information to swapped content
1935-
if (selectionInfo.elt &&
1936-
!bodyContains(selectionInfo.elt) &&
1937-
getRawAttribute(selectionInfo.elt, 'id')) {
1938-
const newActiveElt = document.getElementById(getRawAttribute(selectionInfo.elt, 'id'))
1939-
const focusOptions = { preventScroll: swapSpec.focusScroll !== undefined ? !swapSpec.focusScroll : !htmx.config.defaultFocusScroll }
1940-
if (newActiveElt) {
1875+
// preserve focus and selection
1876+
const activeElt = document.activeElement
1877+
let selectionInfo = {}
1878+
selectionInfo = {
1879+
elt: activeElt,
19411880
// @ts-ignore
1942-
if (selectionInfo.start && newActiveElt.setSelectionRange) {
1943-
try {
1944-
// @ts-ignore
1945-
newActiveElt.setSelectionRange(selectionInfo.start, selectionInfo.end)
1946-
} catch (e) {
1947-
// the setSelectionRange method is present on fields that don't support it, so just let this fail
1881+
start: activeElt ? activeElt.selectionStart : null,
1882+
// @ts-ignore
1883+
end: activeElt ? activeElt.selectionEnd : null
1884+
}
1885+
const settleInfo = makeSettleInfo(target)
1886+
1887+
// For text content swaps, don't parse the response as HTML, just insert it
1888+
if (swapSpec.swapStyle === 'textContent') {
1889+
target.textContent = content
1890+
// Otherwise, make the fragment and process it
1891+
} else {
1892+
let fragment = makeFragment(content)
1893+
1894+
settleInfo.title = fragment.title
1895+
1896+
// select-oob swaps
1897+
if (swapOptions.selectOOB) {
1898+
const oobSelectValues = swapOptions.selectOOB.split(',')
1899+
for (let i = 0; i < oobSelectValues.length; i++) {
1900+
const oobSelectValue = oobSelectValues[i].split(':', 2)
1901+
let id = oobSelectValue[0].trim()
1902+
if (id.indexOf('#') === 0) {
1903+
id = id.substring(1)
1904+
}
1905+
const oobValue = oobSelectValue[1] || 'true'
1906+
const oobElement = fragment.querySelector('#' + id)
1907+
if (oobElement) {
1908+
oobSwap(oobValue, oobElement, settleInfo, rootNode)
1909+
}
19481910
}
19491911
}
1950-
newActiveElt.focus(focusOptions)
1951-
}
1952-
}
1912+
// oob swaps
1913+
findAndSwapOobElements(fragment, settleInfo, rootNode)
1914+
forEach(findAll(fragment, 'template'), /** @param {HTMLTemplateElement} template */function(template) {
1915+
if (template.content && findAndSwapOobElements(template.content, settleInfo, rootNode)) {
1916+
// Avoid polluting the DOM with empty templates that were only used to encapsulate oob swap
1917+
template.remove()
1918+
}
1919+
})
19531920

1954-
target.classList.remove(htmx.config.swappingClass)
1955-
forEach(settleInfo.elts, function(elt) {
1956-
if (elt.classList) {
1957-
elt.classList.add(htmx.config.settlingClass)
1921+
// normal swap
1922+
if (swapOptions.select) {
1923+
const newFragment = getDocument().createDocumentFragment()
1924+
forEach(fragment.querySelectorAll(swapOptions.select), function(node) {
1925+
newFragment.appendChild(node)
1926+
})
1927+
fragment = newFragment
1928+
}
1929+
handlePreservedElements(fragment)
1930+
swapWithStyle(swapSpec.swapStyle, swapOptions.contextElement, target, fragment, settleInfo)
1931+
restorePreservedElements()
19581932
}
1959-
triggerEvent(elt, 'htmx:afterSwap', swapOptions.eventInfo)
1960-
})
1961-
maybeCall(swapOptions.afterSwapCallback)
19621933

1963-
// merge in new title after swap but before settle
1964-
if (!swapSpec.ignoreTitle) {
1965-
handleTitle(settleInfo.title)
1966-
}
1934+
// apply saved focus and selection information to swapped content
1935+
if (selectionInfo.elt &&
1936+
!bodyContains(selectionInfo.elt) &&
1937+
getRawAttribute(selectionInfo.elt, 'id')) {
1938+
const newActiveElt = document.getElementById(getRawAttribute(selectionInfo.elt, 'id'))
1939+
const focusOptions = { preventScroll: swapSpec.focusScroll !== undefined ? !swapSpec.focusScroll : !htmx.config.defaultFocusScroll }
1940+
if (newActiveElt) {
1941+
// @ts-ignore
1942+
if (selectionInfo.start && newActiveElt.setSelectionRange) {
1943+
try {
1944+
// @ts-ignore
1945+
newActiveElt.setSelectionRange(selectionInfo.start, selectionInfo.end)
1946+
} catch (e) {
1947+
// the setSelectionRange method is present on fields that don't support it, so just let this fail
1948+
}
1949+
}
1950+
newActiveElt.focus(focusOptions)
1951+
}
1952+
}
19671953

1968-
// settle
1969-
const doSettle = function() {
1970-
forEach(settleInfo.tasks, function(task) {
1971-
task.call()
1972-
})
1954+
target.classList.remove(htmx.config.swappingClass)
19731955
forEach(settleInfo.elts, function(elt) {
19741956
if (elt.classList) {
1975-
elt.classList.remove(htmx.config.settlingClass)
1957+
elt.classList.add(htmx.config.settlingClass)
19761958
}
1977-
triggerEvent(elt, 'htmx:afterSettle', swapOptions.eventInfo)
1959+
triggerEvent(elt, 'htmx:afterSwap', swapOptions.eventInfo)
19781960
})
1961+
maybeCall(swapOptions.afterSwapCallback)
19791962

1980-
if (swapOptions.anchor) {
1981-
const anchorTarget = asElement(resolveTarget('#' + swapOptions.anchor))
1982-
if (anchorTarget) {
1983-
anchorTarget.scrollIntoView({ block: 'start', behavior: 'auto' })
1984-
}
1963+
// merge in new title after swap but before settle
1964+
if (!swapSpec.ignoreTitle) {
1965+
handleTitle(settleInfo.title)
19851966
}
19861967

1987-
updateScrollState(settleInfo.elts, swapSpec)
1988-
maybeCall(swapOptions.afterSettleCallback)
1989-
maybeCall(settleResolve)
1990-
}
1968+
// settle
1969+
const doSettle = function() {
1970+
forEach(settleInfo.tasks, function(task) {
1971+
task.call()
1972+
})
1973+
forEach(settleInfo.elts, function(elt) {
1974+
if (elt.classList) {
1975+
elt.classList.remove(htmx.config.settlingClass)
1976+
}
1977+
triggerEvent(elt, 'htmx:afterSettle', swapOptions.eventInfo)
1978+
})
19911979

1992-
if (swapSpec.settleDelay > 0) {
1993-
getWindow().setTimeout(doSettle, swapSpec.settleDelay)
1994-
} else {
1995-
doSettle()
1996-
}
1980+
if (swapOptions.anchor) {
1981+
const anchorTarget = asElement(resolveTarget('#' + swapOptions.anchor))
1982+
if (anchorTarget) {
1983+
anchorTarget.scrollIntoView({ block: 'start', behavior: 'auto' })
1984+
}
1985+
}
1986+
1987+
updateScrollState(settleInfo.elts, swapSpec)
1988+
maybeCall(swapOptions.afterSettleCallback)
1989+
maybeCall(settleResolve)
1990+
}
1991+
1992+
if (swapSpec.settleDelay > 0) {
1993+
getWindow().setTimeout(doSettle, swapSpec.settleDelay)
1994+
} else {
1995+
doSettle()
1996+
}
19971997
}
19981998
let shouldTransition = htmx.config.globalViewTransitions
19991999
if (swapSpec.hasOwnProperty('transition')) {
@@ -2011,9 +2011,9 @@ var htmx = (function() {
20112011
settleResolve = _resolve
20122012
settleReject = _reject
20132013
})
2014-
// wrap the original localSwap() in a call to startViewTransition()
2015-
const innerDoSwap = localSwap
2016-
localSwap = function() {
2014+
// wrap the original doSwap() in a call to startViewTransition()
2015+
const innerDoSwap = doSwap
2016+
doSwap = function() {
20172017
// @ts-ignore experimental feature atm
20182018
document.startViewTransition(function() {
20192019
innerDoSwap()
@@ -2024,9 +2024,9 @@ var htmx = (function() {
20242024

20252025
try {
20262026
if (swapSpec?.swapDelay && swapSpec.swapDelay > 0) {
2027-
getWindow().setTimeout(localSwap, swapSpec.swapDelay)
2027+
getWindow().setTimeout(doSwap, swapSpec.swapDelay)
20282028
} else {
2029-
localSwap()
2029+
doSwap()
20302030
}
20312031
} catch (e) {
20322032
triggerErrorEvent(elt, 'htmx:swapError', swapOptions.eventInfo)
@@ -4842,44 +4842,44 @@ var htmx = (function() {
48424842
const selectOOB = getClosestAttributeValue(elt, 'hx-select-oob')
48434843
const select = getClosestAttributeValue(elt, 'hx-select')
48444844

4845-
swap(target, serverResponse, swapSpec, {
4846-
select: selectOverride || select,
4847-
selectOOB,
4848-
eventInfo: responseInfo,
4849-
anchor: responseInfo.pathInfo.anchor,
4850-
contextElement: elt,
4851-
afterSwapCallback: function() {
4852-
if (hasHeader(xhr, /HX-Trigger-After-Swap:/i)) {
4853-
let finalElt = elt
4854-
if (!bodyContains(elt)) {
4855-
finalElt = getDocument().body
4856-
}
4857-
handleTriggerHeader(xhr, 'HX-Trigger-After-Swap', finalElt)
4858-
}
4859-
},
4860-
afterSettleCallback: function() {
4861-
if (hasHeader(xhr, /HX-Trigger-After-Settle:/i)) {
4862-
let finalElt = elt
4863-
if (!bodyContains(elt)) {
4864-
finalElt = getDocument().body
4865-
}
4866-
handleTriggerHeader(xhr, 'HX-Trigger-After-Settle', finalElt)
4867-
}
4868-
},
4869-
beforeSwapCallback: function() {
4870-
// if we need to save history, do so, before swapping so that relative resources have the correct base URL
4871-
if (historyUpdate.type) {
4872-
triggerEvent(getDocument().body, 'htmx:beforeHistoryUpdate', mergeObjects({ history: historyUpdate }, responseInfo))
4873-
if (historyUpdate.type === 'push') {
4874-
pushUrlIntoHistory(historyUpdate.path)
4875-
triggerEvent(getDocument().body, 'htmx:pushedIntoHistory', { path: historyUpdate.path })
4876-
} else {
4877-
replaceUrlInHistory(historyUpdate.path)
4878-
triggerEvent(getDocument().body, 'htmx:replacedInHistory', { path: historyUpdate.path })
4879-
}
4880-
}
4845+
swap(target, serverResponse, swapSpec, {
4846+
select: selectOverride || select,
4847+
selectOOB,
4848+
eventInfo: responseInfo,
4849+
anchor: responseInfo.pathInfo.anchor,
4850+
contextElement: elt,
4851+
afterSwapCallback: function() {
4852+
if (hasHeader(xhr, /HX-Trigger-After-Swap:/i)) {
4853+
let finalElt = elt
4854+
if (!bodyContains(elt)) {
4855+
finalElt = getDocument().body
48814856
}
4882-
})
4857+
handleTriggerHeader(xhr, 'HX-Trigger-After-Swap', finalElt)
4858+
}
4859+
},
4860+
afterSettleCallback: function() {
4861+
if (hasHeader(xhr, /HX-Trigger-After-Settle:/i)) {
4862+
let finalElt = elt
4863+
if (!bodyContains(elt)) {
4864+
finalElt = getDocument().body
4865+
}
4866+
handleTriggerHeader(xhr, 'HX-Trigger-After-Settle', finalElt)
4867+
}
4868+
},
4869+
beforeSwapCallback: function() {
4870+
// if we need to save history, do so, before swapping so that relative resources have the correct base URL
4871+
if (historyUpdate.type) {
4872+
triggerEvent(getDocument().body, 'htmx:beforeHistoryUpdate', mergeObjects({ history: historyUpdate }, responseInfo))
4873+
if (historyUpdate.type === 'push') {
4874+
pushUrlIntoHistory(historyUpdate.path)
4875+
triggerEvent(getDocument().body, 'htmx:pushedIntoHistory', { path: historyUpdate.path })
4876+
} else {
4877+
replaceUrlInHistory(historyUpdate.path)
4878+
triggerEvent(getDocument().body, 'htmx:replacedInHistory', { path: historyUpdate.path })
4879+
}
4880+
}
4881+
}
4882+
})
48834883
}
48844884
if (isError) {
48854885
triggerErrorEvent(elt, 'htmx:responseError', mergeObjects({ error: 'Response Status Error Code ' + xhr.status + ' from ' + responseInfo.pathInfo.requestPath }, responseInfo))

test/attributes/hx-swap.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -318,10 +318,11 @@ describe('hx-swap attribute', function() {
318318
)
319319
div.click()
320320
this.server.respond()
321+
div.innerText.should.equal('')
321322
setTimeout(function() {
322323
div.innerText.should.equal('Clicked!')
323324
done()
324-
}, 100)
325+
}, 30)
325326
})
326327

327328
it('works with a settle delay', function(done) {
@@ -538,8 +539,9 @@ describe('hx-swap attribute', function() {
538539

539540
it('swapError fires if swap throws exception', function() {
540541
try {
541-
htmx._('htmx.backupSwap = swap')
542-
htmx._('swap = function() { throw new Error("throw") }')
542+
// override makeSettleInfo to cause swap function to throw exception
543+
htmx._('htmx.backupMakeSettleInfo = makeSettleInfo')
544+
htmx._('makeSettleInfo = function() { throw new Error("throw") }')
543545
var error = false
544546
var handler = htmx.on('htmx:swapError', function(evt) {
545547
error = true
@@ -554,7 +556,7 @@ describe('hx-swap attribute', function() {
554556
div.innerHTML.should.equal('')
555557
error.should.equal(true)
556558
htmx.off('htmx:swapError', handler)
557-
htmx._('swap = htmx.backupSwap')
559+
htmx._('makeSettleInfo = htmx.backupMakeSettleInfo')
558560
}
559561
})
560562
})

0 commit comments

Comments
 (0)