back out more aggressive validation

This commit is contained in:
carson 2021-03-06 10:52:52 -07:00
parent 3325a9e6ab
commit abd71d6df5
12 changed files with 142 additions and 30 deletions

View File

@ -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

View File

@ -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
View File

@ -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

File diff suppressed because one or more lines are too long

BIN
dist/htmx.min.js.gz vendored

Binary file not shown.

View File

@ -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)

View File

@ -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

View File

@ -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);

View 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!

View File

@ -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);

View File

@ -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");
})
});

View File

@ -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!");
});
})