Merge branch 'master' into dev

This commit is contained in:
carson 2020-05-30 12:05:05 -07:00
commit 533da1c71c
14 changed files with 139 additions and 35 deletions

View File

@ -8,15 +8,16 @@
## introduction
htmx is a set of HTML extensions give you to access to [AJAX](https://htmx.org/docs#ajax),
htmx allows you to access [AJAX](https://htmx.org/docs#ajax),
[WebSockets](https://htmx.org/docs#websockets) and [Server Sent Events](https://htmx.org/docs#sse)
via [attributes](https://htmx.org/reference#attributes), allowing you to build [modern UI](https://htmx.org/examples) with the [simplicity](https://en.wikipedia.org/wiki/HATEOAS) and
directly in HTML, using [attributes](https://htmx.org/reference#attributes), so you can build
[modern user interfaces](https://htmx.org/examples) with the [simplicity](https://en.wikipedia.org/wiki/HATEOAS) and
[power](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm) of hypertext
htmx is small ([~7k min.gz'd](https://unpkg.com/htmx.org/dist/)),
[dependency-free](https://github.com/bigskysoftware/htmx/blob/master/package.json),
[extendable](https://htmx.org/extensions),
IE11 compatible & you can try it out quickly, without a huge rewrite
[extendable](https://htmx.org/extensions) &
IE11 compatible
## quick start
@ -43,7 +44,7 @@ htmx is the successor to [intercooler.js](http://intercoolerjs.org)
## contributing
* please write code, including tests, in ES5 for [IE 11 compatibility](https://stackoverflow.com/questions/39902809/support-for-es6-in-internet-explorer-11)
* please include test cases in `/test` and docs in `/www`
* please include test cases in [`/test`](https://github.com/bigskysoftware/htmx/tree/dev/test) and docs in [`/www`](https://github.com/bigskysoftware/htmx/tree/dev/www)
* if you are adding a feature, consider doing it as an [extension](https://htmx.org/extensions) instead to
keep the core htmx code tidy
* development pull requests should be against the `dev` branch, docs fixes can be made directly against `master`

View File

@ -1,7 +1,7 @@
htmx.defineExtension('json-enc', {
encodeParameters : function(xhr, parameters, elt) {
xhr.requestHeaders['Content-Type'] = 'application/json';
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.overrideMimeType('text/json');
return (JSON.stringify(parameters));
}
});
});

View File

@ -54,12 +54,12 @@ CSS. Here is an example that uses `display` rather than opacity:
}
```
Note that the target of the `ic-indicator` selector need not be the exact element that you
Note that the target of the `hx-indicator` selector need not be the exact element that you
want to show: it can be any element in the parent hierarchy of the indicator.
Finally, note that the `htmx-request` class by default is added to the element causing
the request, so you can place an indicator inside of that element and not need to explictly
call it out with the `ic-indicator` attribute:
call it out with the `hx-indicator` attribute:
```html
<button hx-post="/example">
@ -81,4 +81,4 @@ This simulates what a spinner might look like in that situation:
* `hx-indicator` is inherited and can be placed on a parent element
* In the absence of an explicit indicator, the `htmx-request` class will be added to the element triggering the
request
request

View File

@ -9,7 +9,7 @@ The `hx-target` attribute allows you to target a different element for swapping
request. The value of this attribute can be:
* a CSS query selector of the element to target
* `this` which indicates that the element that the `ic-target` attribute is on is the target
* `this` which indicates that the element that the `hx-target` attribute is on is the target
* `closest <CSS selector>` which will find the closest parent ancestor that matches the given CSS selector.
(e.g. `closest tr` will target the closest table row to the element)

View File

@ -75,7 +75,7 @@ within the language:
* Now any element, not just the entire window, can be the target for update by the request
Note that when you are using htmx, on the server side you respond with *HTML*, not *JSON*. This keeps you firmly
within the [original web programming model]((https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm)),
within the [original web programming model](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm),
using [Hypertext As The Engine Of Application State](https://en.wikipedia.org/wiki/HATEOAS)
without even needing to really understand that concept.
@ -147,7 +147,7 @@ Here is a `div` that posts to `/mouse_entered` when a mouse enters it:
If you want a request to only happen once, you can use the `once` modifier for the trigger:
```html
<div hx-post="/mouse_entered" hx-trigger="mouseenter once"">
<div hx-post="/mouse_entered" hx-trigger="mouseenter once">
[Here Mouse, Mouse!]
</div>
```
@ -189,7 +189,7 @@ If you want an element to poll the given URL rather than wait for an event, you
with the [`hx-trigger`](/attributes/hx-trigger/) attribute:
```html
<div hx-get="/news" trigger="every 2s">
<div hx-get="/news" hx-trigger="every 2s">
</div>
```

View File

@ -226,7 +226,7 @@ than a single value.
##### Details
* `detail.parameters` - the parameters that will be submitted in the request
* `detail.unfilteredParameters` - the parameters that were found before filtering by [`ic-select`](/attributes/ic-select)
* `detail.unfilteredParameters` - the parameters that were found before filtering by [`hx-select`](/attributes/hx-select)
* `detail.headers` - the request headers
* `detail.elt` - the element that triggered the request
* `detail.target` - the target of the request

View File

@ -127,12 +127,8 @@ You can see a working examle of this code below.
// templates
function displayUI(contacts) {
return `<div hx-include="#checked-contacts" hx-target="#tbody">
<a class="btn" hx-put="/activate">Activate</a>
<a class="btn" hx-put="/deactivate">Deactivate</a>
</div>
<form id="checked-contacts">
return `<h3>Select Rows And Activate Or Deactivate Below<h3>
<form id="checked-contacts">
<table>
<thead>
<tr>
@ -146,7 +142,12 @@ You can see a working examle of this code below.
${displayTable([], contacts, "")}
</tbody>
</table>
</form>`
</form>
<br/>
<div hx-include="#checked-contacts" hx-target="#tbody">
<a class="btn" hx-put="/activate">Activate</a>
<a class="btn" hx-put="/deactivate">Deactivate</a>
</div>`
}
function displayTable(ids, contacts, action) {

View File

@ -87,7 +87,7 @@ Below is a working demo of this example. The only email that will be accepted i
// routes
init("/demo", function(request, params){
return formTemplate();
return demoTemplate();
});
onPost("/contact", function(request, params){
@ -106,8 +106,13 @@ Below is a working demo of this example. The only email that will be accepted i
});
// templates
function formTemplate(page) {
return `<h3>Signup Form</h3><form ic-post-to="/contact">
function demoTemplate() {
return `<h3>Signup Form</h3><p>Enter an email into the input below and on tab out it will be validated. Only "test@test.com" will pass.</p> ` + formTemplate();
}
function formTemplate() {
return `<form hx-post="/contact">
<div hx-target="this" hx-swap="outerHTML">
<label>Email Address</label>
<input name="email" hx-get="/contact/email" hx-indicator="#ind">
@ -121,7 +126,7 @@ Below is a working demo of this example. The only email that will be accepted i
<label>Last Name</label>
<input type="text" class="form-control" name="lastName">
</div>
<button class="btn btn-default">Submit</button>
<button class="btn btn-default" disabled>Submit</button>
</form>`;
}

View File

@ -18,6 +18,12 @@ To use an extension you use the [hx-ext](/attributes/hx-ext) attribute:
Note that the `hx-ext` tag may be placed on parent elements if you want a plugin to apply to an entire swath of the dom,
and on the `body` tag for it to apply to all htmx requests.
**Tip:** To use multiple extensions on one element, separate them with a comma:
```html
<button hx-post="/example" hx-ext="debug, json-enc">This Button Uses Two Extensions</button>
```
## <a name="included"></a> [Included Extensions](#included)
The following extensions that are tested and distributed with htmx:
@ -63,4 +69,4 @@ Extensions can override the following default extension fields:
handleSwap : function(swapStyle, target, fragment, settleInfo) {return false;},
encodeParameters : function(xhr, parameters, elt) {return null;}
}
```
```

View File

@ -13,7 +13,7 @@ swapped into the DOM. Currently three client-side templating engines are suppor
* [nunjucks](https://mozilla.github.io/nunjucks/)
When you add this extension on an element, any element below it in the DOM can use one of three attributes named
`<template-engine>-temlpate` (e.g. `mustache-template`) with a template ID, and the extension will resolve and render
`<template-engine>-template` (e.g. `mustache-template`) with a template ID, and the extension will resolve and render
the template the standard way for that template engine:
* `mustache` - looks a mustache &lt;script> tag up by ID for the template content

View File

@ -13,7 +13,6 @@ will be evaluated as the fields in a javascript object literal.
```html
<div hx-ext="include-vals">
<!-- Removes this div after 1 second -->
<div hx-get="/test" include-vals="included:true, computed: computeValue()">
Will Include Additional Values
</div>
@ -22,4 +21,4 @@ will be evaluated as the fields in a javascript object literal.
### Source
<https://unpkg.com/htmx.org/dist/ext/remove-me.js>
<https://unpkg.com/htmx.org/dist/ext/include-vals.js>

View File

@ -11,15 +11,16 @@ title: </> htmx - high power tools for html
## introduction
htmx is a set of HTML extensions give you to access to [AJAX](https://htmx.org/docs#ajax),
htmx allows you to access [AJAX](https://htmx.org/docs#ajax),
[WebSockets](https://htmx.org/docs#websockets) and [Server Sent Events](https://htmx.org/docs#sse)
via [attributes](https://htmx.org/reference#attributes), allowing you to build [modern UI](https://htmx.org/examples) with the [simplicity](https://en.wikipedia.org/wiki/HATEOAS) and
directly in HTML, using [attributes](https://htmx.org/reference#attributes), so you can build
[modern user interfaces](https://htmx.org/examples) with the [simplicity](https://en.wikipedia.org/wiki/HATEOAS) and
[power](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm) of hypertext
htmx is small ([~7k min.gz'd](https://unpkg.com/htmx.org/dist/)),
[dependency-free](https://github.com/bigskysoftware/htmx/blob/master/package.json),
[extendable](/extensions),
IE11 compatible & you can try it out quickly, without a huge rewrite
[extendable](https://htmx.org/extensions) &
IE11 compatible
## quick start

View File

@ -0,0 +1,91 @@
---
layout: layout.njk
title: </> htmx - high power tools for html
---
## Locality of Behaviour (LoB)
> "The primary feature for easy maintenance is locality: Locality is that characteristic of source code that enables a
> programmer to understand that source by looking at only a small portion of it." -- [Richard Gabriel](https://www.dreamsongs.com/Files/PatternsOfSoftware.pdf)
### The LoB Principle:
> The behaviour of a code unit should be as obvious as possible by looking only at that unit of code
### Discussion
The LoB principle is a simple prescriptive formulation of the quoted statement from [Richard Gabriel](https://www.dreamsongs.com).
In as much as it is possible, and in balance with other concerns, developers should strive to make the behaviour of
a code element obvious on inspection.
Consider two different implementations of an AJAX request in HTML, the first in [htmx](https://htmx.org):
```html
<div hx-get="/clicked">Click Me</div>
```
and the second in [jQuery](https://jquery.com/):
```javascript
$("#d1").on("click", function(){
$.ajax({
...
});
});
```
```html
<div id="d1">Click Me</div>
```
In the former, the behaviour of the `div` element is obvious on inspection, satisfying the LoB principle.
In the latter, the behaviour of the `div` element is spread out amongst multiple files. It is difficult to know
exactly what the div does without a total knowledge of the code base.
#### Surfacing Behaviour vs. Inlining Implementation
A common conflation is surfacing behaviour with inlining implementation of that behaviour. These are separate concepts
and, while inlining the implementation of a behaviour isn't *always* incorrect, it may *often* be incorrect.
Increasing the obviousness of the behaviour of an element is, ceteris paribus, a good thing, but it falls to both end-developers
and especially framework developers to make LoB as easy as possible.
#### Conflict With Other Development Principles
The LoB will often conflict with other software development principles. Two important ones
are:
* [DRY - Don't Repeat Yourself](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)
Software developers typically strive to avoid redundancy in their code or data. This as come to be called "Staying DRY",
i.e. Don't Repeat Yourself. Like other software design principles this, on its own, is a good thing. htmx, for example,
allows you to place many attributes on parent elements in a DOM and avoid repeating these attributes on children. This is a
violation of LoB, in favor of DRY, and such tradeoffs need to be made judiciously by developers.
Note that the further behaviour gets from the code unit it effects, the more severe the violation of LoB. If it is
within a few lines of the code unit, this is less serious than if it is a page away, which is less serious than if
it is in a separate file entirely.
There is no hard and fast rule, but rather subjective tradeoffs that must be made as software developers.
* [SoC - Separation Of Concerns](https://en.wikipedia.org/wiki/Separation_of_concerns)
Separation of concerns a design principle for separating a computer program into distinct sections such that each
section addresses a separate concern. A canonical example of this is CSS vs. Javascript. Again, on its own and
in isolation this may, indeed, be a good thing. Inlining styles has become more prevalent lately, but there are
still strong arguments in favor of SoC in this regard.
Note that SoC is, however, in conflict with LoB. By tweaking a CSS file the look and, to an extent, behaviour of an
element can change dramatically, and it is not obvious where this dramatic change came from. Tools help to an extent
here, but there is still "spooky action at a distance" going on.
Again, this isn't to condemn SoC wholesale, just to say that there are subjective tradeoffs that must be made when
considering how to structure your code. The fact that inline styles have become more prevalent as of late is an
indication that SoC is losing some support amongst developers.
#### Conclusion
LoB is a software design principle that can help make a code bases more humane and maintainable. It must be traded
off against other design principles and be considered in terms of the limitations of the system a code unit is
written in, but, as much as is it is practical, adherence to this principle will increase your developer productivity
and well-being.

View File

@ -62,7 +62,7 @@ title: </> htmx - Attributes
| `X-HX-Active-Element` | the `id` of the active element if it exists
| `X-HX-Current-URL` | the current URL of the browser
| `X-HX-Event-Target` | the `id` of the original event target
| `X-HX-Prompt` | the user response to an [ic-prompt](/attributes/hx-prompt)
| `X-HX-Prompt` | the user response to an [hx-prompt](/attributes/hx-prompt)
| `X-HX-Request` | always `true`
| `X-HX-Target` | the `id` of the target element if it exists
| `X-HX-Trigger-Name` | the `name` of the triggered element if it exists