mirror of
https://github.com/bigskysoftware/htmx.git
synced 2025-09-27 04:50:43 +00:00
back out more aggressive validation
This commit is contained in:
parent
3325a9e6ab
commit
abd71d6df5
11
CHANGELOG.md
11
CHANGELOG.md
@ -1,6 +1,17 @@
|
||||
# Changelog
|
||||
|
||||
|
||||
## [1.3.0] - 2021-3-6
|
||||
|
||||
* Support a `target` modifier on `hx-trigger` to filter based on the element targeted by an event. This allows
|
||||
lazy binding to that target selector.
|
||||
* Events are no longer consumed by the first element that might handle them, unless the `consume` keyword is
|
||||
added to the `hx-trigger` specification
|
||||
* Added the `htmx:beforeSend` event, fired just before an ajax request begins
|
||||
* SSE swaps are properly settled
|
||||
* Fixed bug that was improperly cancelling all clicks on anchors
|
||||
* `htmx.ajax()` now returns a promise
|
||||
|
||||
## [1.2.1] - 2021-2-19
|
||||
|
||||
* Fixed an issue with the history cache, where the cache was getting blown out after the first navigation backwards
|
||||
|
@ -35,7 +35,7 @@ By removing these arbitrary constraints htmx completes HTML as a
|
||||
|
||||
```html
|
||||
<!-- Load from unpkg -->
|
||||
<script src="https://unpkg.com/htmx.org@1.2.1" ></script>
|
||||
<script src="https://unpkg.com/htmx.org@1.3.0" ></script>
|
||||
<!-- have a button POST a click via AJAX -->
|
||||
<button hx-post="/clicked" hx-swap="outerHTML">
|
||||
Click Me
|
||||
|
35
dist/htmx.js
vendored
35
dist/htmx.js
vendored
@ -22,6 +22,10 @@ return (function () {
|
||||
find : find,
|
||||
findAll : findAll,
|
||||
closest : closest,
|
||||
values : function(elt, type){
|
||||
var inputValues = getInputValues(elt, type || "post");
|
||||
return inputValues.values;
|
||||
},
|
||||
remove : removeElement,
|
||||
addClass : addClassToElement,
|
||||
removeClass : removeClassFromElement,
|
||||
@ -698,8 +702,8 @@ return (function () {
|
||||
var fragment = makeFragment(responseText);
|
||||
if (fragment) {
|
||||
handleOutOfBandSwaps(fragment, settleInfo);
|
||||
handlePreservedElements(fragment);
|
||||
fragment = maybeSelectFromResponse(elt, fragment);
|
||||
handlePreservedElements(fragment);
|
||||
return swap(swapStyle, elt, target, fragment, settleInfo);
|
||||
}
|
||||
}
|
||||
@ -1940,18 +1944,27 @@ return (function () {
|
||||
function ajaxHelper(verb, path, context) {
|
||||
if (context) {
|
||||
if (context instanceof Element || isType(context, 'String')) {
|
||||
return issueAjaxRequest(verb, path, null, null, null, resolveTarget(context));
|
||||
return issueAjaxRequest(verb, path, null, null, {
|
||||
targetOverride: resolveTarget(context)
|
||||
});
|
||||
} else {
|
||||
return issueAjaxRequest(verb, path, resolveTarget(context.source), context.event, context.handler, resolveTarget(context.target));
|
||||
return issueAjaxRequest(verb, path, resolveTarget(context.source), context.event,
|
||||
{
|
||||
handler : context.handler,
|
||||
headers : context.headers,
|
||||
values : context.values,
|
||||
targetOverride: resolveTarget(context.target)
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return issueAjaxRequest(verb, path);
|
||||
}
|
||||
}
|
||||
|
||||
function issueAjaxRequest(verb, path, elt, event, responseHandler, targetOverride) {
|
||||
function issueAjaxRequest(verb, path, elt, event, etc) {
|
||||
var resolve = null;
|
||||
var reject = null;
|
||||
etc = etc != null ? etc : {};
|
||||
var promise = new Promise(function (_resolve, _reject) {
|
||||
resolve = _resolve;
|
||||
reject = _reject;
|
||||
@ -1959,13 +1972,12 @@ return (function () {
|
||||
if(elt == null) {
|
||||
elt = getDocument().body;
|
||||
}
|
||||
if (responseHandler == null) {
|
||||
responseHandler = handleAjaxResponse;
|
||||
}
|
||||
var responseHandler = etc.handler || handleAjaxResponse;
|
||||
|
||||
if (!bodyContains(elt)) {
|
||||
return; // do not issue requests for elements removed from the DOM
|
||||
}
|
||||
var target = targetOverride || getTarget(elt);
|
||||
var target = etc.targetOverride || getTarget(elt);
|
||||
if (target == null) {
|
||||
triggerErrorEvent(elt, 'htmx:targetError', {target: getAttributeValue(elt, "hx-target")});
|
||||
return;
|
||||
@ -2010,9 +2022,15 @@ return (function () {
|
||||
var xhr = new XMLHttpRequest();
|
||||
|
||||
var headers = getHeaders(elt, target, promptResponse);
|
||||
if (etc.headers) {
|
||||
headers = mergeObjects(headers, etc.values);
|
||||
}
|
||||
var results = getInputValues(elt, verb);
|
||||
var errors = results.errors;
|
||||
var rawParameters = results.values;
|
||||
if (etc.values) {
|
||||
rawParameters = mergeObjects(rawParameters, etc.values);
|
||||
}
|
||||
var expressionVars = getExpressionVars(elt);
|
||||
var allParameters = mergeObjects(rawParameters, expressionVars);
|
||||
var filteredParameters = filterValues(allParameters, elt);
|
||||
@ -2146,6 +2164,7 @@ return (function () {
|
||||
})
|
||||
});
|
||||
});
|
||||
triggerEvent(elt, 'htmx:beforeSend', responseInfo);
|
||||
xhr.send(verb === 'get' ? null : encodeParamsForBody(xhr, elt, filteredParameters));
|
||||
return promise;
|
||||
}
|
||||
|
2
dist/htmx.min.js
vendored
2
dist/htmx.min.js
vendored
File diff suppressed because one or more lines are too long
BIN
dist/htmx.min.js.gz
vendored
BIN
dist/htmx.min.js.gz
vendored
Binary file not shown.
@ -97,13 +97,13 @@ It can be used via [NPM](https://www.npmjs.com/) as "`htmx.org`" or downloaded o
|
||||
[unpkg](https://unpkg.com/browse/htmx.org/) or your other favorite NPM-based CDN:
|
||||
|
||||
``` html
|
||||
<script src="https://unpkg.com/htmx.org@1.2.1"></script>
|
||||
<script src="https://unpkg.com/htmx.org@1.3.0"></script>
|
||||
```
|
||||
|
||||
For added security, you can load the script using [Subresource Integrity (SRI)](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity).
|
||||
|
||||
``` html
|
||||
<script src="https://unpkg.com/htmx.org@1.2.1" integrity="sha384-t37OW0DbqgL50XZW+Tl8TLchxsPoxIJ7NQ/l4aSZIXZVJQAhyQvvkWZgL/SiY/jD" crossorigin="anonymous"></script>
|
||||
<script src="https://unpkg.com/htmx.org@1.3.0" integrity="sha384-SRglfaqPHLuqU8LUUSQoeTFBY7CNqaVDs3vy/TONuLgrQu/UVJ/BvC0DPn4ZGcJ4" crossorigin="anonymous"></script>
|
||||
```
|
||||
|
||||
## <a name="ajax"></a> [AJAX](#ajax)
|
||||
|
@ -35,7 +35,7 @@ By removing these arbitrary constraints htmx completes HTML as a
|
||||
|
||||
```html
|
||||
<!-- Load from unpkg -->
|
||||
<script src="https://unpkg.com/htmx.org@1.2.1"></script>
|
||||
<script src="https://unpkg.com/htmx.org@1.3.0"></script>
|
||||
<!-- have a button POST a click via AJAX -->
|
||||
<button hx-post="/clicked" hx-swap="outerHTML">
|
||||
Click Me
|
||||
|
@ -22,6 +22,10 @@ return (function () {
|
||||
find : find,
|
||||
findAll : findAll,
|
||||
closest : closest,
|
||||
values : function(elt, type){
|
||||
var inputValues = getInputValues(elt, type || "post");
|
||||
return inputValues.values;
|
||||
},
|
||||
remove : removeElement,
|
||||
addClass : addClassToElement,
|
||||
removeClass : removeClassFromElement,
|
||||
@ -698,8 +702,8 @@ return (function () {
|
||||
var fragment = makeFragment(responseText);
|
||||
if (fragment) {
|
||||
handleOutOfBandSwaps(fragment, settleInfo);
|
||||
handlePreservedElements(fragment);
|
||||
fragment = maybeSelectFromResponse(elt, fragment);
|
||||
handlePreservedElements(fragment);
|
||||
return swap(swapStyle, elt, target, fragment, settleInfo);
|
||||
}
|
||||
}
|
||||
@ -1940,18 +1944,27 @@ return (function () {
|
||||
function ajaxHelper(verb, path, context) {
|
||||
if (context) {
|
||||
if (context instanceof Element || isType(context, 'String')) {
|
||||
return issueAjaxRequest(verb, path, null, null, null, resolveTarget(context));
|
||||
return issueAjaxRequest(verb, path, null, null, {
|
||||
targetOverride: resolveTarget(context)
|
||||
});
|
||||
} else {
|
||||
return issueAjaxRequest(verb, path, resolveTarget(context.source), context.event, context.handler, resolveTarget(context.target));
|
||||
return issueAjaxRequest(verb, path, resolveTarget(context.source), context.event,
|
||||
{
|
||||
handler : context.handler,
|
||||
headers : context.headers,
|
||||
values : context.values,
|
||||
targetOverride: resolveTarget(context.target)
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return issueAjaxRequest(verb, path);
|
||||
}
|
||||
}
|
||||
|
||||
function issueAjaxRequest(verb, path, elt, event, responseHandler, targetOverride) {
|
||||
function issueAjaxRequest(verb, path, elt, event, etc) {
|
||||
var resolve = null;
|
||||
var reject = null;
|
||||
etc = etc != null ? etc : {};
|
||||
var promise = new Promise(function (_resolve, _reject) {
|
||||
resolve = _resolve;
|
||||
reject = _reject;
|
||||
@ -1959,13 +1972,12 @@ return (function () {
|
||||
if(elt == null) {
|
||||
elt = getDocument().body;
|
||||
}
|
||||
if (responseHandler == null) {
|
||||
responseHandler = handleAjaxResponse;
|
||||
}
|
||||
var responseHandler = etc.handler || handleAjaxResponse;
|
||||
|
||||
if (!bodyContains(elt)) {
|
||||
return; // do not issue requests for elements removed from the DOM
|
||||
}
|
||||
var target = targetOverride || getTarget(elt);
|
||||
var target = etc.targetOverride || getTarget(elt);
|
||||
if (target == null) {
|
||||
triggerErrorEvent(elt, 'htmx:targetError', {target: getAttributeValue(elt, "hx-target")});
|
||||
return;
|
||||
@ -2010,9 +2022,15 @@ return (function () {
|
||||
var xhr = new XMLHttpRequest();
|
||||
|
||||
var headers = getHeaders(elt, target, promptResponse);
|
||||
if (etc.headers) {
|
||||
headers = mergeObjects(headers, etc.values);
|
||||
}
|
||||
var results = getInputValues(elt, verb);
|
||||
var errors = results.errors;
|
||||
var rawParameters = results.values;
|
||||
if (etc.values) {
|
||||
rawParameters = mergeObjects(rawParameters, etc.values);
|
||||
}
|
||||
var expressionVars = getExpressionVars(elt);
|
||||
var allParameters = mergeObjects(rawParameters, expressionVars);
|
||||
var filteredParameters = filterValues(allParameters, elt);
|
||||
|
26
www/posts/2021-3-6-htmx-1.3.0-is-released.md
Normal file
26
www/posts/2021-3-6-htmx-1.3.0-is-released.md
Normal file
@ -0,0 +1,26 @@
|
||||
---
|
||||
layout: layout.njk
|
||||
tags: post
|
||||
title: htmx 1.2.0 has been released!
|
||||
date: 2021-03-06
|
||||
---
|
||||
|
||||
## htmx 1.3.0 Release
|
||||
|
||||
I'm happy to announce the [1.3.0 release](https://unpkg.com/browse/htmx.org@1.3.0/) of htmx.
|
||||
|
||||
### New Features & Major Changes
|
||||
|
||||
* Support a `target` modifier on `hx-trigger` to filter based on the element targeted by an event. This allows
|
||||
lazy binding to that target selector.
|
||||
* Events are no longer consumed by the first element that might handle them, unless the `consume` keyword is
|
||||
added to the `hx-trigger` specification
|
||||
* Added the `htmx:beforeSend` event, fired just before an ajax request begins
|
||||
* `htmx.ajax()` now returns a promise
|
||||
|
||||
### Improvements & Bug fixes
|
||||
|
||||
* SSE swaps are properly settled
|
||||
* Fixed bug that was improperly cancelling all clicks on anchors
|
||||
|
||||
Enjoy!
|
@ -22,6 +22,10 @@ return (function () {
|
||||
find : find,
|
||||
findAll : findAll,
|
||||
closest : closest,
|
||||
values : function(elt, type){
|
||||
var inputValues = getInputValues(elt, type || "post");
|
||||
return inputValues.values;
|
||||
},
|
||||
remove : removeElement,
|
||||
addClass : addClassToElement,
|
||||
removeClass : removeClassFromElement,
|
||||
@ -698,8 +702,8 @@ return (function () {
|
||||
var fragment = makeFragment(responseText);
|
||||
if (fragment) {
|
||||
handleOutOfBandSwaps(fragment, settleInfo);
|
||||
handlePreservedElements(fragment);
|
||||
fragment = maybeSelectFromResponse(elt, fragment);
|
||||
handlePreservedElements(fragment);
|
||||
return swap(swapStyle, elt, target, fragment, settleInfo);
|
||||
}
|
||||
}
|
||||
@ -1940,18 +1944,27 @@ return (function () {
|
||||
function ajaxHelper(verb, path, context) {
|
||||
if (context) {
|
||||
if (context instanceof Element || isType(context, 'String')) {
|
||||
return issueAjaxRequest(verb, path, null, null, null, resolveTarget(context));
|
||||
return issueAjaxRequest(verb, path, null, null, {
|
||||
targetOverride: resolveTarget(context)
|
||||
});
|
||||
} else {
|
||||
return issueAjaxRequest(verb, path, resolveTarget(context.source), context.event, context.handler, resolveTarget(context.target));
|
||||
return issueAjaxRequest(verb, path, resolveTarget(context.source), context.event,
|
||||
{
|
||||
handler : context.handler,
|
||||
headers : context.headers,
|
||||
values : context.values,
|
||||
targetOverride: resolveTarget(context.target)
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return issueAjaxRequest(verb, path);
|
||||
}
|
||||
}
|
||||
|
||||
function issueAjaxRequest(verb, path, elt, event, responseHandler, targetOverride) {
|
||||
function issueAjaxRequest(verb, path, elt, event, etc) {
|
||||
var resolve = null;
|
||||
var reject = null;
|
||||
etc = etc != null ? etc : {};
|
||||
var promise = new Promise(function (_resolve, _reject) {
|
||||
resolve = _resolve;
|
||||
reject = _reject;
|
||||
@ -1959,13 +1972,12 @@ return (function () {
|
||||
if(elt == null) {
|
||||
elt = getDocument().body;
|
||||
}
|
||||
if (responseHandler == null) {
|
||||
responseHandler = handleAjaxResponse;
|
||||
}
|
||||
var responseHandler = etc.handler || handleAjaxResponse;
|
||||
|
||||
if (!bodyContains(elt)) {
|
||||
return; // do not issue requests for elements removed from the DOM
|
||||
}
|
||||
var target = targetOverride || getTarget(elt);
|
||||
var target = etc.targetOverride || getTarget(elt);
|
||||
if (target == null) {
|
||||
triggerErrorEvent(elt, 'htmx:targetError', {target: getAttributeValue(elt, "hx-target")});
|
||||
return;
|
||||
@ -2010,9 +2022,15 @@ return (function () {
|
||||
var xhr = new XMLHttpRequest();
|
||||
|
||||
var headers = getHeaders(elt, target, promptResponse);
|
||||
if (etc.headers) {
|
||||
headers = mergeObjects(headers, etc.values);
|
||||
}
|
||||
var results = getInputValues(elt, verb);
|
||||
var errors = results.errors;
|
||||
var rawParameters = results.values;
|
||||
if (etc.values) {
|
||||
rawParameters = mergeObjects(rawParameters, etc.values);
|
||||
}
|
||||
var expressionVars = getExpressionVars(elt);
|
||||
var allParameters = mergeObjects(rawParameters, expressionVars);
|
||||
var filteredParameters = filterValues(allParameters, elt);
|
||||
|
@ -26,5 +26,14 @@ describe("hx-preserve attribute", function () {
|
||||
byId("d2").innerHTML.should.equal("New Content");
|
||||
})
|
||||
|
||||
it('preserved element should not be swapped if it lies outside of hx-select', function () {
|
||||
this.server.respondWith("GET", "/test", "<div id='d1' hx-preserve>New Content</div><div id='d2'>New Content</div>");
|
||||
var div = make("<div hx-get='/test' hx-target='#d2' hx-select='#d2' hx-swap='outerHTML'><div id='d1' hx-preserve>Old Content</div><div id='d2'>Old Content</div></div>");
|
||||
div.click();
|
||||
this.server.respond();
|
||||
byId("d1").innerHTML.should.equal("Old Content");
|
||||
byId("d2").innerHTML.should.equal("New Content");
|
||||
})
|
||||
|
||||
});
|
||||
|
||||
|
@ -291,6 +291,17 @@ describe("Core htmx API test", function(){
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
it('ajax api can pass parameters', function()
|
||||
{
|
||||
this.server.respondWith("POST", "/test", function (xhr) {
|
||||
var params = getParameters(xhr);
|
||||
params['i1'].should.equal("test");
|
||||
xhr.respond(200, {}, "Clicked!")
|
||||
});
|
||||
var div = make("<div id='d1'></div>");
|
||||
htmx.ajax("POST", "/test", {target:"#d1", values:{i1: 'test'}})
|
||||
this.server.respond();
|
||||
div.innerHTML.should.equal("Clicked!");
|
||||
});
|
||||
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user