diff --git a/src/htmx.js b/src/htmx.js index 3bf1d2e6c..f27bb95b6 100644 --- a/src/htmx.js +++ b/src/htmx.js @@ -1560,10 +1560,8 @@ var htmx = (function() { forEach(fragment.querySelectorAll('[id]'), function(newNode) { const id = getRawAttribute(newNode, 'id') if (id && id.length > 0) { - const normalizedId = id.replace("'", "\\'") - const normalizedTag = newNode.tagName.replace(':', '\\:') const parentElt = asParentNode(parentNode) - const oldNode = parentElt && parentElt.querySelector(normalizedTag + "[id='" + normalizedId + "']") + const oldNode = parentElt && parentElt.querySelector(CSS.escape(newNode.tagName) + '#' + CSS.escape(id)) if (oldNode && oldNode !== parentElt) { const newAttributes = newNode.cloneNode() cloneAttributes(newNode, oldNode) @@ -1979,7 +1977,7 @@ var htmx = (function() { removeClassFromElement(target, htmx.config.swappingClass) forEach(settleInfo.elts, function(elt) { if (elt.classList) { - elt.classList.add(htmx.config.settlingClass) + addClassToElement(elt, htmx.config.settlingClass) } triggerEvent(elt, 'htmx:afterSwap', swapOptions.eventInfo) }) @@ -3378,7 +3376,7 @@ var htmx = (function() { forEach(indicators, function(ic) { const internalData = getInternalData(ic) internalData.requestCount = (internalData.requestCount || 0) + 1 - ic.classList.add.call(ic.classList, htmx.config.requestClass) + addClassToElement(ic, htmx.config.requestClass) }) return indicators } @@ -4915,7 +4913,7 @@ var htmx = (function() { swapSpec.ignoreTitle = ignoreTitle } - target.classList.add(htmx.config.swappingClass) + addClassToElement(target, htmx.config.swappingClass) if (responseInfoSelect) { selectOverride = responseInfoSelect diff --git a/test/core/ajax.js b/test/core/ajax.js index 9adbfc05a..eeef65e65 100644 --- a/test/core/ajax.js +++ b/test/core/ajax.js @@ -341,6 +341,18 @@ describe('Core htmx AJAX Tests', function() { }, 20) }) + it('properly settles attributes elements with multiple single quotes in id', function(done) { + this.server.respondWith('GET', '/test', "
") + var div = make("
") + div.click() + this.server.respond() + should.equal(byId("fo'o'bar").getAttribute('width'), null) + setTimeout(function() { + should.equal(byId("fo'o'bar").getAttribute('width'), 'bar') + done() + }, 20) + }) + it('properly settles attributes elements with double quotes in id', function(done) { this.server.respondWith('GET', '/test', "
") var div = make("
") @@ -992,6 +1004,20 @@ describe('Core htmx AJAX Tests', function() { btn.innerHTML.should.equal('Foobar') }) + it('falls back to DOMParser when parseHTMLUnsafe is not available', function() { + const original = Document.parseHTMLUnsafe + try { + delete Document.parseHTMLUnsafe + this.server.respondWith('GET', '/test', '
Fallback
') + var div = make('
') + div.click() + this.server.respond() + div.innerHTML.should.equal('
Fallback
') + } finally { + Document.parseHTMLUnsafe = original + } + }) + it('properly handles clicked submit button with a value inside a htmx form', function() { var values this.server.respondWith('Post', '/test', function(xhr) {