diff --git a/src/htmx.js b/src/htmx.js index 304905bb..56e3495b 100644 --- a/src/htmx.js +++ b/src/htmx.js @@ -2181,24 +2181,33 @@ return (function () { delete extensions[name]; } - function getExtensions(elt, extensionsToReturn) { - if (elt == null) { + function getExtensions(elt, extensionsToReturn, extensionsToIgnore) { + if (elt == undefined) { return extensionsToReturn; } - if (extensionsToReturn == null) { + if (extensionsToReturn == undefined) { extensionsToReturn = []; } + if (extensionsToIgnore == undefined) { + extensionsToIgnore = []; + } var extensionsForElement = getAttributeValue(elt, "hx-ext"); if (extensionsForElement) { forEach(extensionsForElement.split(","), function(extensionName){ extensionName = extensionName.replace(/ /g, ''); - var extension = extensions[extensionName]; - if (extension && extensionsToReturn.indexOf(extension) < 0) { - extensionsToReturn.push(extension); + if (extensionName.slice(0, 7) == "ignore:") { + extensionsToIgnore.push(extensionName.slice(7)); + return; + } + if (extensionsToIgnore.indexOf(extensionName) < 0) { + var extension = extensions[extensionName]; + if (extension && extensionsToReturn.indexOf(extension) < 0) { + extensionsToReturn.push(extension); + } } }); } - return getExtensions(parentElt(elt), extensionsToReturn); + return getExtensions(parentElt(elt), extensionsToReturn, extensionsToIgnore); } //==================================================================== diff --git a/test/attributes/hx-ext.js b/test/attributes/hx-ext.js index 6c7c92c0..740b9bd8 100644 --- a/test/attributes/hx-ext.js +++ b/test/attributes/hx-ext.js @@ -110,7 +110,29 @@ describe("hx-ext attribute", function() { ext2Calls.should.equal(0); ext3Calls.should.equal(0); ext4Calls.should.equal(1); + }); + it('Extensions are ignored properly', function () { + this.server.respondWith("GET", "/test", "Clicked!"); + + make('
' + + '
') + + var btn1 = byId("btn-AA"); + var btn2 = byId("btn-BB"); + + btn1.click(); + this.server.respond(); + ext1Calls.should.equal(1); + ext2Calls.should.equal(1); + ext3Calls.should.equal(0); + + btn2.click(); + this.server.respond(); + ext1Calls.should.equal(1); + ext2Calls.should.equal(2); + ext3Calls.should.equal(0); + }) }); \ No newline at end of file diff --git a/www/attributes/hx-ext.md b/www/attributes/hx-ext.md index 166a0e99..d0ee81aa 100644 --- a/www/attributes/hx-ext.md +++ b/www/attributes/hx-ext.md @@ -16,3 +16,16 @@ and on the `body` tag for it to apply to all htmx requests. * `hx-ext` is both inherited and merged with parent elements, so you can specify extensions on any element in the DOM hierarchy and it will apply to all child elements. + +* You can ignore an extension that is defined by a parent node using `hx-ext="ignore:extensionName"` + + +```html +
+ "Example" extension is used in this part of the tree... +
+ ... but it will not be used in this part. +
+
+``` + diff --git a/www/docs.md b/www/docs.md index 0ba5478e..6541f121 100644 --- a/www/docs.md +++ b/www/docs.md @@ -636,7 +636,10 @@ Htmx has an extension mechanism that allows you to customize the libraries' beha defined in javascript](/extensions#defining) and then used via the [`hx-ext`](/attributes/hx-ext) attribute: ```html - +
+ + +
``` If you are interested in adding your own extension to htmx, please [see the extension docs](/extensions) diff --git a/www/extensions.md b/www/extensions.md index cae31b2e..cf25c8db 100644 --- a/www/extensions.md +++ b/www/extensions.md @@ -33,6 +33,18 @@ and on the `body` tag for it to apply to all htmx requests. ``` +## [Ignoring Extensions](#ignoring) + +By default, extensions are applied to the DOM node where it is invoked, along with all child elements inside of that parent node. +If you need to disable an extension somewhere within the DOM tree, you can use the `ignore:` keyword to stop it from being used. + +```html +
+ + +
+``` + ## [Included Extensions](#included) htmx includes a set of extensions out of the box that address common developer needs. These extensions are tested