summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorp.b <1430300+pbt@users.noreply.github.com>2024-02-29 11:11:46 -0500
committerGitHub <noreply@github.com>2024-02-29 11:11:46 -0500
commitd1fc7895f65b9235a2f5daa63060a94b6d2252c4 (patch)
tree2935a058dd2808decf1eee7f6605519e5fe4c5b5
parentf004978bbbf68befb49bfef7f17a2ec25ce35ae0 (diff)
downloadhtmx-d1fc7895f65b9235a2f5daa63060a94b6d2252c4.tar.gz
htmx-d1fc7895f65b9235a2f5daa63060a94b6d2252c4.zip
Add textContent swap style (#2356)
* feat: add textContent swap style * add documentation --------- Co-authored-by: pbt <pb.to@icloud.com>
-rw-r--r--src/htmx.js75
-rw-r--r--test/attributes/hx-swap.js47
-rw-r--r--www/content/attributes/hx-swap.md1
3 files changed, 88 insertions, 35 deletions
diff --git a/src/htmx.js b/src/htmx.js
index 9935979f..19c66629 100644
--- a/src/htmx.js
+++ b/src/htmx.js
@@ -1805,46 +1805,51 @@ var htmx = (function() {
}
const settleInfo = makeSettleInfo(target)
- let fragment = makeFragment(content)
-
- settleInfo.title = fragment.title
-
- // select-oob swaps
- if (swapOptions.selectOOB) {
- const oobSelectValues = swapOptions.selectOOB.split(',')
- for (let i = 0; i < oobSelectValues.length; i++) {
- const oobSelectValue = oobSelectValues[i].split(':', 2)
- let id = oobSelectValue[0].trim()
- if (id.indexOf('#') === 0) {
- id = id.substring(1)
- }
- const oobValue = oobSelectValue[1] || 'true'
- const oobElement = fragment.querySelector('#' + id)
- if (oobElement) {
- oobSwap(oobValue, oobElement, settleInfo)
+ if (swapSpec.swapStyle === 'textContent') {
+ // parse only as text; don't process OOB swaps
+ target.textContent = content
+ } else {
+ let fragment = makeFragment(content)
+
+ settleInfo.title = fragment.title
+
+ // select-oob swaps
+ if (swapOptions.selectOOB) {
+ const oobSelectValues = swapOptions.selectOOB.split(',')
+ for (let i = 0; i < oobSelectValues.length; i++) {
+ const oobSelectValue = oobSelectValues[i].split(':', 2)
+ let id = oobSelectValue[0].trim()
+ if (id.indexOf('#') === 0) {
+ id = id.substring(1)
+ }
+ const oobValue = oobSelectValue[1] || 'true'
+ const oobElement = fragment.querySelector('#' + id)
+ if (oobElement) {
+ oobSwap(oobValue, oobElement, settleInfo)
+ }
}
}
- }
- // oob swaps
- findAndSwapOobElements(fragment, settleInfo)
- forEach(findAll(fragment, 'template'), /** @param {HTMLTemplateElement} template */function(template) {
- findAndSwapOobElements(template.content, settleInfo)
- if (template.content.childElementCount === 0) {
+ // oob swaps
+ findAndSwapOobElements(fragment, settleInfo)
+ forEach(findAll(fragment, 'template'), /** @param {HTMLTemplateElement} template */function(template) {
+ findAndSwapOobElements(template.content, settleInfo)
+ if (template.content.childElementCount === 0) {
// Avoid polluting the DOM with empty templates that were only used to encapsulate oob swap
- template.remove()
- }
- })
-
- // normal swap
- if (swapOptions.select) {
- const newFragment = getDocument().createDocumentFragment()
- forEach(fragment.querySelectorAll(swapOptions.select), function(node) {
- newFragment.appendChild(node)
+ template.remove()
+ }
})
- fragment = newFragment
+
+ // normal swap
+ if (swapOptions.select) {
+ const newFragment = getDocument().createDocumentFragment()
+ forEach(fragment.querySelectorAll(swapOptions.select), function(node) {
+ newFragment.appendChild(node)
+ })
+ fragment = newFragment
+ }
+ handlePreservedElements(fragment)
+ swapWithStyle(swapSpec.swapStyle, swapOptions.contextElement, target, fragment, settleInfo)
}
- handlePreservedElements(fragment)
- swapWithStyle(swapSpec.swapStyle, swapOptions.contextElement, target, fragment, settleInfo)
// apply saved focus and selection information to swapped content
if (selectionInfo.elt &&
diff --git a/test/attributes/hx-swap.js b/test/attributes/hx-swap.js
index ac405d75..d3e9099b 100644
--- a/test/attributes/hx-swap.js
+++ b/test/attributes/hx-swap.js
@@ -22,6 +22,53 @@ describe('hx-swap attribute', function() {
a.innerHTML.should.equal('Clicked!')
})
+ it('swap textContent properly with HTML tags', function() {
+ this.server.respondWith('GET', '/test', '<a id="a1" hx-get="/test2">Click Me</a>')
+
+ var d1 = make('<div id="d1" hx-get="/test" hx-swap="textContent"></div>')
+ d1.click()
+ should.equal(byId('d1'), d1)
+ this.server.respond()
+ d1.textContent.should.equal('<a id="a1" hx-get="/test2">Click Me</a>')
+ should.equal(byId('a1'), null)
+ })
+
+ it('swap textContent properly with HTML tags and text', function() {
+ this.server.respondWith('GET', '/test', 'text content <a id="a1" hx-get="/test2">Click Me</a>')
+
+ var d1 = make('<div id="d1" hx-get="/test" hx-swap="textContent"></div>')
+ d1.click()
+ should.equal(byId('d1'), d1)
+ this.server.respond()
+ d1.textContent.should.equal('text content <a id="a1" hx-get="/test2">Click Me</a>')
+ should.equal(byId('a1'), null)
+ })
+
+ it('swap textContent ignores OOB swaps', function() {
+ this.server.respondWith('GET', '/test', '<span id="d2" hx-swap-oob="true">hi</span> <a id="a1" hx-get="/test2">Click Me</a>')
+
+ var d1 = make('<div id="d1" hx-get="/test" hx-swap="textContent"></div>')
+ var d2 = make('<div id="d2">some text</div>')
+ d1.click()
+ should.equal(byId('d1'), d1)
+ should.equal(byId('d2'), d2)
+ this.server.respond()
+ d1.textContent.should.equal('<span id="d2" hx-swap-oob="true">hi</span> <a id="a1" hx-get="/test2">Click Me</a>')
+ d2.outerHTML.should.equal('<div id="d2">some text</div>')
+ should.equal(byId('a1'), null)
+ })
+
+ it('swap textContent properly with text', function() {
+ this.server.respondWith('GET', '/test', 'plain text')
+
+ var div = make('<div id="d1" hx-get="/test" hx-swap="textContent"></div>')
+ div.click()
+ should.equal(byId('d1'), div)
+ this.server.respond()
+ div.textContent.should.equal('plain text')
+ should.equal(byId('a1'), null)
+ })
+
it('swap outerHTML properly', function() {
this.server.respondWith('GET', '/test', '<a id="a1" hx-get="/test2">Click Me</a>')
this.server.respondWith('GET', '/test2', 'Clicked!')
diff --git a/www/content/attributes/hx-swap.md b/www/content/attributes/hx-swap.md
index f4ef401a..d7593985 100644
--- a/www/content/attributes/hx-swap.md
+++ b/www/content/attributes/hx-swap.md
@@ -10,6 +10,7 @@ The possible values of this attribute are:
* `innerHTML` - Replace the inner html of the target element
* `outerHTML` - Replace the entire target element with the response
+* `textContent` - Replace the text content of the target element, without parsing the response as HTML
* `beforebegin` - Insert the response before the target element
* `afterbegin` - Insert the response before the first child of the target element
* `beforeend` - Insert the response after the last child of the target element