Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/htmx.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,13 @@ export function findAll(selector: string): NodeListOf<Element>;
*/
export function findAll(elt: Element, selector: string): NodeListOf<Element>;

/**
* When htmx is imported as a module, this function must be called to initialize it.
*
* https://htmx.org/api/#start
*/
export function start(): void;

/**
* Log all htmx events, useful for debugging.
*
Expand Down Expand Up @@ -288,6 +295,8 @@ export function values(elt: Element, requestType?: string): any;
export const version: string;

export interface HtmxConfig {
/** whether or not htmx should be initialized automatically when DOM is ready */
autoStart?: boolean;
/** array of strings: the attributes to settle during the settling phase */
attributesToSettle?: ["class", "style", "width", "height"] | string[];
/** if the focused element should be scrolled into view */
Expand Down
50 changes: 42 additions & 8 deletions src/htmx.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ return (function () {
//** @type {import("./htmx").HtmxApi} */
// TODO: list all methods in public API
var htmx = {
start: start,
onLoad: onLoadHelper,
process: processNode,
on: addEventListenerImpl,
Expand All @@ -47,6 +48,7 @@ return (function () {
logNone : logNone,
logger : null,
config : {
autoStart: document.currentScript !== null, // do not initialize htmx automatically if executed as module
historyEnabled:true,
historyCacheSize:10,
refreshOnHistoryMiss:false,
Expand Down Expand Up @@ -2102,6 +2104,14 @@ return (function () {
}
}

function logWarn(msg) {
if(console.warn) {
console.warn(msg);
} else if (console.log) {
console.log("WARN: ", msg);
}
}

function triggerEvent(elt, eventName, detail) {
elt = resolveTarget(elt);
if (detail == null) {
Expand Down Expand Up @@ -3633,29 +3643,43 @@ return (function () {
}
}

var metaConfigLoaded = false;
function mergeMetaConfig() {
if (metaConfigLoaded) {
return;
}

var metaConfig = getMetaConfig();
if (metaConfig) {
htmx.config = mergeObjects(htmx.config , metaConfig)
}
metaConfigLoaded = true;
}

// initialize the document
ready(function () {
var started = false;
function start() {
if (started) {
logWarn('htmx has already been initialized on this page. Calling htmx.start() more than once may cause problems.');
}
started = true;

var body = getDocument().body;
if (!body) {
logError('Unable to initialize. Trying to load htmx before `<body>` is available. Did you forget to add `defer` in htmx\'s `<script>` tag?');
}

mergeMetaConfig();
insertIndicatorStyles();
var body = getDocument().body;
processNode(body);
var restoredElts = getDocument().querySelectorAll(
"[hx-trigger='restored'],[data-hx-trigger='restored']"
);

body.addEventListener("htmx:abort", function (evt) {
var target = evt.target;
var internalData = getInternalData(target);
if (internalData && internalData.xhr) {
internalData.xhr.abort();
}
});

var restoredElts = getDocument().querySelectorAll('[hx-trigger="restored"],[data-hx-trigger="restored"]');
var originalPopstate = window.onpopstate;
window.onpopstate = function (event) {
if (event.state && event.state.htmx) {
Expand All @@ -3672,11 +3696,21 @@ return (function () {
}
}
};

setTimeout(function () {
processNode(body);
triggerEvent(body, 'htmx:load', {}); // give ready handlers a chance to load up before firing this event
body = null; // kill reference for gc
}, 0);
})
}

// initialize if auto start is enabled
ready(function() {
mergeMetaConfig();
if (htmx.config.autoStart) {
start();
}
});

return htmx;
}
Expand Down
14 changes: 14 additions & 0 deletions www/content/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ Note that using a [meta tag](@/docs.md#config) is the preferred mechanism for se

##### Properties

* `autoStart:true` - boolean: whether or not htmx should be initialized automatically when DOM is ready. If htmx is loaded as module this defaults to `false` and you must initialize htmx manually by calling `htmx.start()`
* `attributesToSettle:["class", "style", "width", "height"]` - array of strings: the attributes to settle during the settling phase
* `defaultSettleDelay:20` - int: the default delay between completing the content swap and settling attributes
* `defaultSwapDelay:0` - int: the default delay between receiving a response from the server and doing the swap
Expand Down Expand Up @@ -230,6 +231,19 @@ or
var allParagraphsInMyDiv = htmx.findAll(htmx.find("#my-div"), "p")
```

### Method - `htmx.start()` {#start}

When htmx is imported as a module, this function must be called to initialize it.

##### Example

```js
import htmx from 'htmx.org';
import '<extensions>';

htmx.start();
```

### Method - `htmx.logAll()` {#logAll}

Log all htmx events, useful for debugging.
Expand Down
40 changes: 15 additions & 25 deletions www/content/docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,44 +132,34 @@ and include it where necessary with a `<script>` tag:

You can also add extensions this way, by downloading them from the `ext/` directory.

### npm
### As a Module

For npm-style build systems, you can install htmx via [npm](https://www.npmjs.com/):
You can install htmx via NPM or Yarn and import it into a bundle.

Install via [npm](https://www.npmjs.com/):

```sh
npm install htmx.org
npm i htmx.org
```

After installing, you’ll need to use appropriate tooling to use `node_modules/htmx.org/dist/htmx.js` (or `.min.js`).
For example, you might bundle htmx with some extensions and project-specific code.

### Webpack

If you are using webpack to manage your javascript:
Install via [yarn](https://yarnpkg.com/):

* Install `htmx` via your favourite package manager (like npm or yarn)
* Add the import to your `index.js`

```js
import 'htmx.org';
```sh
yarn add htmx.org
```

If you want to use the global `htmx` variable (recommended), you need to inject it to the window scope:

* Create a custom JS file
* Import this file to your `index.js` (below the import from step 2)
Now import htmx into your bundle and initialize it like so:

```js
import 'path/to/my_custom.js';
```
import htmx from 'htmx.org';
import '<extensions>'

* Then add this code to the file:
window.htmx = htmx;

```js
window.htmx = require('htmx.org');
htmx.start();
```

* Finally, rebuild your bundle
>The window.htmx = htmx is optional, but is nice to have for freedom and flexibility.
>If you have imported htmx into a bundle, you must ensure that you have imported or registered any extension after the import of htmx and before the initialization `htmx.start()`.

## AJAX

Expand Down