diff options
-rw-r--r-- | .circleci/config.yml | 22 | ||||
-rw-r--r-- | package.json | 1 | ||||
-rw-r--r-- | src/htmx.js | 10 | ||||
-rw-r--r-- | test/index.html | 1 | ||||
-rw-r--r-- | www/api.md | 9 | ||||
-rw-r--r-- | www/docs.md | 8 | ||||
-rw-r--r-- | www/essays/a-response-to-rich-harris.md | 8 | ||||
-rw-r--r-- | www/examples/active-search.md | 16 | ||||
-rw-r--r-- | www/examples/progress-bar.md | 2 | ||||
-rw-r--r-- | www/extensions/path-deps.md | 2 | ||||
-rw-r--r-- | www/talk.md | 2 |
11 files changed, 61 insertions, 20 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 00000000..c29ebc77 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,22 @@ +version: 2.1 + +commands: + +orbs: + browser-tools: circleci/browser-tools@1.1.0 +jobs: + test: + docker: + - image: cimg/node:16.13.1-browsers + steps: + - browser-tools/install-browser-tools + - checkout + - run: | + node --version + java --version + google-chrome --version + +workflows: + tests-containers: + jobs: + - test diff --git a/package.json b/package.json index 27e27e2f..9498be65 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "fs-extra": "^9.1.0", "mocha": "^7.2.0", "mocha-chrome": "^2.2.0", + "mocha-webdriver-runner": "^0.6.3", "sass": "^1.34.0", "sinon": "^9.2.4", "typescript": "^4.3.5", diff --git a/src/htmx.js b/src/htmx.js index 6f5d788f..adf923eb 100644 --- a/src/htmx.js +++ b/src/htmx.js @@ -347,9 +347,13 @@ return (function () { return elemTop < window.innerHeight && elemBottom >= 0; } - function bodyContains(elt) { - return getDocument().body.contains(elt); - } + function bodyContains(elt) { + if (elt.getRootNode() instanceof ShadowRoot) { + return getDocument().body.contains(elt.getRootNode().host); + } else { + return getDocument().body.contains(elt); + } + } function splitOnWhitespace(trigger) { return trigger.trim().split(/\s+/); diff --git a/test/index.html b/test/index.html index 457b90c4..359156c2 100644 --- a/test/index.html +++ b/test/index.html @@ -30,6 +30,7 @@ <script src="../node_modules/chai/chai.js"></script> <script src="../node_modules/mocha/mocha.js"></script> +<script src="../node_modules/mocha-webdriver-runner/dist/mocha-webdriver-client.js"></script> <script src="../node_modules/sinon/pkg/sinon.js"></script> <script src="../src/htmx.js"></script> <script class="mocha-init"> @@ -28,7 +28,7 @@ This method adds a class to the given element. ### <a name="ajax"></a> Method - [`htmx.ajax()`](#ajax) -Issues an htmx-style AJAX request +Issues an htmx-style AJAX request. This method returns a Promise, so a callback can be executed after the content has been inserted into the DOM. ##### Parameters @@ -60,6 +60,13 @@ or ```js // issue a GET to /example and put the response HTML into #myDiv htmx.ajax('GET', '/example', '#myDiv') + + // execute some code after the content has been inserted into the DOM + htmx.ajax('GET', '/example', '#myDiv').then(() => { + // this code will be executed after the 'htmx:afterOnLoad' event, + // and before the 'htmx:xhr:loadend' event + console.log('Content inserted successfully!'); + }); ``` ### <a name="closest"></a> Method - [`htmx.closest()`](#closest) diff --git a/www/docs.md b/www/docs.md index 6c08021f..6e9c7537 100644 --- a/www/docs.md +++ b/www/docs.md @@ -385,7 +385,7 @@ content of the page is examined for elements that match by the `id` attribute. is found for an element in the new content, the attributes of the old content are copied onto the new element before the swap occurs. The new content is then swapped in, but with the *old* attribute values. Finally, the new attribute values are swapped in, after a "settle" delay -(100ms by default). A little crazy, but this is what allowes CSS transitions to work without any javascript by +(20ms by default). A little crazy, but this is what allowes CSS transitions to work without any javascript by the developer. #### <a name="oob_swaps"></a>[Out of Band Swaps](#oob_swaps) @@ -681,7 +681,7 @@ The order of operations in a htmx request are: * the `htmx-swapping` class is removed from the target * the `htmx-added` class is added to each new piece of content * the `htmx-settling` class is applied to the target - * A settle delay is done (default: 100ms) + * A settle delay is done (default: 20ms) * The DOM is settled * the `htmx-settling` class is removed from the target * the `htmx-added` class is removed from each new piece of content @@ -860,7 +860,7 @@ If you set a logger at `htmx.logger`, every event will be logged. This can be v ## <a name="debugging"></a> [Debugging](#debugging) Declarative and event driven programming with htmx (or any other declartive language) can be a wonderful and highly productive -activity, but one disadvantage when compared with imperative approaches is that it can be tricker to debug. +activity, but one disadvantage when compared with imperative approaches is that it can be trickier to debug. Figuring out why something *isn't* happening, for example, can be difficult if you don't know the tricks. @@ -1102,7 +1102,7 @@ listed below: | `htmx.config.refreshOnHistoryMiss` | defaults to `false`, if set to `true` htmx will issue a full page refresh on history misses rather than use an AJAX request | `htmx.config.defaultSwapStyle` | defaults to `innerHTML` | `htmx.config.defaultSwapDelay` | defaults to 0 -| `htmx.config.defaultSettleDelay` | defaults to 100 +| `htmx.config.defaultSettleDelay` | defaults to 20 | `htmx.config.includeIndicatorStyles` | defaults to `true` (determines if the indicator styles are loaded) | `htmx.config.indicatorClass` | defaults to `htmx-indicator` | `htmx.config.requestClass` | defaults to `htmx-request` diff --git a/www/essays/a-response-to-rich-harris.md b/www/essays/a-response-to-rich-harris.md index 84143139..ed1043bc 100644 --- a/www/essays/a-response-to-rich-harris.md +++ b/www/essays/a-response-to-rich-harris.md @@ -61,7 +61,7 @@ preserve a particular piece of content between requests. ### "Back Button & Infinite Scroll Don't Work" -In the presence of infinite scroll behavior (presumably implemented via javascript of some sort) the back button will not work properly with an MPA. I would note that the presence of infinite scroll calls into question the term MPA, which would traditionally use paging instead of an infinte scroll. +In the presence of infinite scroll behavior (presumably implemented via javascript of some sort) the back button will not work properly with an MPA. I would note that the presence of infinite scroll calls into question the term MPA, which would traditionally use paging instead of an infinite scroll. That said, [infinite scroll](/examples/infinite-scroll) can be achieved quite easily using htmx, in a hypermedia-oriented and obvious manner. When combined with the [`hx-push-url`](/attributes/hx-push-url) attribute, history and the back button works properly with very little effort by the developer, all with nice Copy-and-Pasteable URLs, sometimes referred to as "Deep Links" by people in the SPA community. @@ -99,7 +99,7 @@ require far more sophisticated engineering work to resolve. Mr. Harris then discusses the concept of "transitional applications" which are a mix of both SPA and MPA technologies. This terminology is reasonable, and we will see if the term sticks in the industry. -We often recommend using htmx for the parts of the app it makes sense to keep things simple, and then using other +We often recommend using htmx for the parts of the app where it makes sense to keep things simple, and then using other technologies when needed: [alpine.js](https://alpinejs.dev/), [hyperscript](https://hyperscript.org), a small reactive framework, etc. @@ -190,7 +190,7 @@ the backend that a huge javascript front end produces. You can still use javasc but you use it in the manner it was originally intended: as a light, front end scripting language for enhancing your application. Or, if you are brave, perhaps you can try [hyperscript](https://hyperscript.org) for these needs. -This is a world we would prefer live in: many programming language options, each with their own strengths, technical cultures and thriving +This is a world we would prefer to live in: many programming language options, each with their own strengths, technical cultures and thriving communities, all able to participate in the web development world through the magic of more powerful hypermedia, rather than a monolith of SPAs-talking-to-Node-in-JSON. Diversity, after all, is our strength. @@ -200,4 +200,4 @@ In conclusion,  -</div>
\ No newline at end of file +</div> diff --git a/www/examples/active-search.md b/www/examples/active-search.md index 7f2b7cbd..b21e48dd 100644 --- a/www/examples/active-search.md +++ b/www/examples/active-search.md @@ -15,10 +15,10 @@ We start with a search input and an empty table: <img src="/img/bars.svg"/> Searching... </span> </h3> -<input class="form-control" type="text" +<input class="form-control" type="search" name="search" placeholder="Begin Typing To Search Users..." hx-post="/search" - hx-trigger="keyup changed delay:500ms" + hx-trigger="keyup changed delay:500ms, search" hx-target="#search-results" hx-indicator=".htmx-indicator"> @@ -41,6 +41,11 @@ We add the `delay:500ms` modifier to the trigger to delay sending the query unti we add the `changed` modifier to the trigger to ensure we don't send new queries when the user doesn't change the value of the input (e.g. they hit an arrow key). +Since we use a `search` type input we will get an `x` in the input field to clear the input. +To make this trigger a new `POST` we have to specify another trigger. We specify another trigger by using a comma to +separate them. The `search` trigger will be run when the field is cleared but it also makes it possible to override +the 500 ms delay on `keyup` by just pressing enter. + Finally, we show an indicator when the search is in flight with the `hx-indicator` attribute. @@ -72,10 +77,10 @@ Search Contacts </span> </h3> -<input class="form-control" type="text" +<input class="form-control" type="search" name="search" placeholder="Begin Typing To Search Users..." hx-post="/search" - hx-trigger="keyup changed delay:500ms" + hx-trigger="keyup changed delay:500ms, search" hx-target="#search-results" hx-indicator=".htmx-indicator"> @@ -209,9 +214,10 @@ Search Contacts return { findContactsMatching : function(str) { var result = []; + var s = str.toLowerCase(); for (var i = 0; i < data.length; i++) { var c = data[i]; - if(c['FirstName'].indexOf(str) >= 0 || c['LastName'].indexOf(str) >= 0 || c['Email'].indexOf(str) >= 0) { + if(c['FirstName'].toLowerCase().indexOf(s) >= 0 || c['LastName'].toLowerCase().indexOf(s) >= 0 || c['Email'].toLowerCase().indexOf(s) >= 0) { result.push(c) } } diff --git a/www/examples/progress-bar.md b/www/examples/progress-bar.md index 2d6142e4..dfde533c 100644 --- a/www/examples/progress-bar.md +++ b/www/examples/progress-bar.md @@ -6,7 +6,7 @@ layout: demo_layout.njk This example shows how to implement a smoothly scrolling progress bar. -We start with an intial state with a button that issues a `POST` to `/start` to begin the job: +We start with an initial state with a button that issues a `POST` to `/start` to begin the job: ```html <div hx-target="this" hx-swap="outerHTML"> diff --git a/www/extensions/path-deps.md b/www/extensions/path-deps.md index 65fb2916..94290bcc 100644 --- a/www/extensions/path-deps.md +++ b/www/extensions/path-deps.md @@ -6,7 +6,7 @@ title: </> htmx - high power tools for html ## The `path-deps` Extension This extension supports expressing inter-element dependencies based on paths, inspired by the -[intercooler.js dependencies mechanism.](http://intercoolerjs.org/docs.html#dependencies). When this +[intercooler.js dependencies mechanism](http://intercoolerjs.org/docs.html#dependencies). When this extension is installed an element can express a dependency on another path by using the `path-deps` property and then setting `hx-trigger` to `path-deps`: diff --git a/www/talk.md b/www/talk.md index 5555a0a0..57c0d837 100644 --- a/www/talk.md +++ b/www/talk.md @@ -66,7 +66,7 @@ Email: [htmx@bigsky.software](mailto:htmx@bigsky.software) * [Software Breakthroughs for the 21s Century](https://www.youtube.com/watch?v=O4ZFIx1ckSg) * [Django Chat](https://djangochat.com/episodes/htmx-carson-gross) * [Talk Python](https://talkpython.fm/episodes/show/321/htmx-clean-dynamic-html-pages) -* [.NET Rocks!](https://podtail.com/en/podcast/-net-rocks/htmx-with-carson-gross/) +* [.NET Rocks!](https://www.dotnetrocks.com/?show=1749) [Contact Us](mailto:podcasts@bigsky.software) to Join You on Your Podcast! |