htmx.ext...chunked-transfer
Version:
Chunked transfer encoding extension for htmx.
117 lines (99 loc) • 2.71 kB
text/typescript
//
import type { HtmxExtension } from "htmx.org";
//
(function () {
let api: HtmxApi;
htmx.defineExtension("chunked-transfer", {
init: function (apiRef: HtmxApi) {
api = apiRef;
},
onEvent: function (name, evt) {
const elt = evt.target as Element;
const target = api.getTarget(elt);
if (name === "htmx:beforeRequest") {
const xhr = evt.detail.xhr as XMLHttpRequest;
xhr.onprogress = function () {
const is_chunked =
xhr.getResponseHeader("Transfer-Encoding") === "chunked";
if (!is_chunked) return;
let response = xhr.response as string;
api.withExtensions(elt, function (extension) {
if (!extension.transformResponse) return;
response = extension.transformResponse(response, xhr, elt);
});
var swapSpec = api.getSwapSpecification(elt);
var settleInfo = api.makeSettleInfo(elt);
if (api.swap) {
api.swap(target, response, swapSpec);
} else {
api.selectAndSwap(
swapSpec.swapStyle,
target,
elt,
response,
settleInfo,
);
}
api.settleImmediately(settleInfo.tasks);
};
}
},
} as HtmxExtension & { init: (apiRef: any) => void });
})();
//
declare global {
var htmx: typeof import("htmx.org");
interface Window {
htmx: typeof import("htmx.org");
}
}
//
// Inspired by https://github.com/delaneyj/nothtmx2
interface HtmxApi {
defineExtension(name: string, extension: HtmxExtension): void;
getSwapSpecification(elt: Element): SwapSpec;
getTarget(elt: Element): Element;
makeSettleInfo(elt: Element): SettleInfo;
selectAndSwap( // HTMX 1.0
swapStyle: string,
target: Element,
elt: Element,
responseText: string,
settleInfo: SettleInfo,
): void;
swap( // HTMX 2.0
target: Element,
content: string,
swapSpec: SwapSpec,
swapOptions?: SwapOptions,
): void;
settleImmediately(tasks: Task[]): void;
withExtensions(
elt: Element,
callback: (extension: HtmxExtension) => void,
): void;
}
interface SwapSpec {
swapStyle: string;
swapDelay: Number;
settleDelay: Number;
transition: Boolean;
ignoreTitle: Boolean;
head: string;
// scroll, scrollTarget, show, showTarget, focusScroll
}
interface SwapOptions {
select: string;
selectOOB: string;
eventInfo: Object;
anchor: Element;
contextElement: Element;
afterSwapCallback: () => void;
afterSettleCallback: () => void;
}
interface SettleInfo {
title?: string;
elts: Element[];
tasks: Task[];
}
export type Task = () => void;