diff --git a/src/htmx.js b/src/htmx.js index 37ad22698..580e42c9b 100644 --- a/src/htmx.js +++ b/src/htmx.js @@ -233,6 +233,12 @@ var htmx = (function() { * @default ['get', 'delete'] */ methodsThatUseUrlParams: ['get', 'delete'], + /** + * Custom HTTP verbs allowed to be parsed as attribute in form hx-custom-verb-XXX or data-hx-custom-verb-XXX where XXX is the custom verb + * @type {(String)[]} + * @default [] + */ + customVerbs: [], /** * If set to true, disables htmx-based requests to non-origin hosts. * @type boolean @@ -354,7 +360,11 @@ var htmx = (function() { const VERBS = ['get', 'post', 'put', 'delete', 'patch'] const VERB_SELECTOR = VERBS.map(function(verb) { return '[hx-' + verb + '], [data-hx-' + verb + ']' - }).join(', ') + }).concat( + htmx.config.customVerbs.map(function(verb) { + return '[hx-custom-verb-' + verb + '], [data-hx-custom-verb-' + verb + ']' + }) + ).join(', ') //= =================================================================== // Utilities @@ -2669,9 +2679,11 @@ var htmx = (function() { */ function processVerbs(elt, nodeData, triggerSpecs) { let explicitAction = false - forEach(VERBS, function(verb) { - if (hasAttribute(elt, 'hx-' + verb)) { - const path = getAttributeValue(elt, 'hx-' + verb) + const verbsWithAssociatedAttributes = VERBS.map(function(verb) { return [verb, 'hx-' + verb] }) + const customVerbsWithAssociatedAttributes = htmx.config.customVerbs.map(function(verb) { return [verb, 'hx-custom-verb-' + verb] }) + forEach(verbsWithAssociatedAttributes.concat(customVerbsWithAssociatedAttributes), function([verb, attribute]) { + if (hasAttribute(elt, attribute)) { + const path = getAttributeValue(elt, attribute) explicitAction = true nodeData.path = path nodeData.verb = verb diff --git a/test/attributes/hx-custom-verb-wildcard.js b/test/attributes/hx-custom-verb-wildcard.js new file mode 100644 index 000000000..a573f61f3 --- /dev/null +++ b/test/attributes/hx-custom-verb-wildcard.js @@ -0,0 +1,51 @@ +describe('hx-custom-verb attribute', function() { + beforeEach(function() { + this.server = makeServer() + clearWorkArea() + }) + afterEach(function() { + this.server.restore() + clearWorkArea() + }) + + it('issues a custom verb request', function() { + this.server.respondWith('RESET_PASSWORD', '/test', function(xhr) { + xhr.respond(200, {}, 'Password reset!') + }) + make('') + + var btn = make('') + btn.click() + this.server.respond() + btn.innerHTML.should.equal('Password reset!') + + make('') + }) + + it('issues a custom verb request w/ data-* prefix', function() { + this.server.respondWith('RESET_PASSWORD', '/test', function(xhr) { + xhr.respond(200, {}, 'Password reset!') + }) + make('') + + var btn = make('') + btn.click() + this.server.respond() + btn.innerHTML.should.equal('Password reset!') + + make('') + }) + + it('does not issues a custom verb request if the config is not set', function() { + this.server.respondWith('RESET_PASSWORD', '/test', function(xhr) { + xhr.respond(200, {}, 'Password reset!') + }) + + // Do not add configuration to prove effectiveness + var btn = make('') + btn.click() + this.server.respond() + btn.innerHTML.should.not.equal('Password reset!') + btn.innerHTML.should.equal('Click me!') + }) +}) diff --git a/test/index.html b/test/index.html index fb4473b0b..894efa7df 100644 --- a/test/index.html +++ b/test/index.html @@ -81,6 +81,7 @@