mirror of
https://github.com/bigskysoftware/htmx.git
synced 2025-09-28 05:21:18 +00:00
more release prep
This commit is contained in:
parent
666b4cbaa8
commit
ba03597a65
82
dist/htmx.js
vendored
82
dist/htmx.js
vendored
@ -368,23 +368,26 @@ return (function () {
|
||||
});
|
||||
}
|
||||
|
||||
function handleAttributes(parentNode, fragment, settleInfo) {
|
||||
forEach(fragment.querySelectorAll("[id]"), function (newNode) {
|
||||
var oldNode = parentNode.querySelector(newNode.tagName + "[id=" + newNode.id + "]")
|
||||
if (oldNode && oldNode !== parentNode) {
|
||||
var newAttributes = newNode.cloneNode();
|
||||
cloneAttributes(newNode, oldNode);
|
||||
settleInfo.tasks.push(function () {
|
||||
cloneAttributes(newNode, newAttributes);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function insertNodesBefore(parentNode, insertBefore, fragment, settleInfo) {
|
||||
handleAttributes(parentNode, fragment, settleInfo);
|
||||
while(fragment.childNodes.length > 0){
|
||||
var child = fragment.firstChild;
|
||||
parentNode.insertBefore(child, insertBefore);
|
||||
if (child.nodeType !== Node.TEXT_NODE) {
|
||||
var newAttributes = null;
|
||||
if (child.id) {
|
||||
var originalNode = parentNode.querySelector(child.tagName + "[id=" + child.id + "]");
|
||||
if (originalNode && originalNode !== parentNode) {
|
||||
newAttributes = child.cloneNode();
|
||||
cloneAttributes(child, originalNode);
|
||||
}
|
||||
}
|
||||
settleInfo.tasks.push(function(){
|
||||
if (newAttributes) {
|
||||
cloneAttributes(child, newAttributes);
|
||||
}
|
||||
processNode(child);
|
||||
triggerEvent(child, 'load.htmx', {});
|
||||
});
|
||||
@ -519,6 +522,8 @@ return (function () {
|
||||
|
||||
if (trigger === "every")
|
||||
return {trigger: 'every', pollInterval: parseInterval(tokens[1])};
|
||||
if (trigger.indexOf("sse:") === 0)
|
||||
return {trigger: 'sse', sseEvent: trigger.substr(4)};
|
||||
|
||||
var triggerSpec = {trigger: trigger};
|
||||
for (var i = 1; i < tokens.length; i++) {
|
||||
@ -662,22 +667,18 @@ return (function () {
|
||||
function processWebSocketInfo(elt, nodeData, info) {
|
||||
var values = info.split(",");
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
var value = removeWhiteSpace(values[i]);
|
||||
if (value.indexOf("source:") === 0) {
|
||||
processWebSocketSource(elt, value.substr(7));
|
||||
var value = splitOnWhitespace(values[i]);
|
||||
if (value[0] === "connect") {
|
||||
processWebSocketSource(elt, value[1]);
|
||||
}
|
||||
if (value.indexOf("send:") === 0) {
|
||||
processWebSocketSend(elt, value.substr(5));
|
||||
if (value[0] === "send") {
|
||||
processWebSocketSend(elt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function processWebSocketSource(elt, wssSource) {
|
||||
var detail = {
|
||||
protocols:[]
|
||||
};
|
||||
triggerEvent(elt, "initWebSocket.htmx", detail);
|
||||
var socket = new WebSocket("wss:" + wssSource, detail.protocols);
|
||||
var socket = htmx.createWebSocket(wssSource);
|
||||
socket.onerror = function (e) {
|
||||
triggerErrorEvent(elt, "wsError.htmx", {error:e, socket:socket});
|
||||
maybeCloseWebSocketSource(elt);
|
||||
@ -712,13 +713,13 @@ return (function () {
|
||||
}
|
||||
}
|
||||
|
||||
function processWebSocketSend(elt, eventName) {
|
||||
function processWebSocketSend(elt) {
|
||||
var webSocketSourceElt = getClosestMatch(elt, function (parent) {
|
||||
return getInternalData(parent).webSocket != null;
|
||||
});
|
||||
if (webSocketSourceElt) {
|
||||
var webSocket = getInternalData(webSocketSourceElt).webSocket;
|
||||
elt.addEventListener(eventName, function (evt) {
|
||||
elt.addEventListener(getTriggerSpecs(elt)[0].trigger, function (evt) {
|
||||
var headers = getHeaders(elt, webSocketSourceElt, null, elt);
|
||||
var rawParameters = getInputValues(elt, 'post');
|
||||
var filteredParameters = filterValues(rawParameters, elt);
|
||||
@ -743,18 +744,15 @@ return (function () {
|
||||
function processSSEInfo(elt, nodeData, info) {
|
||||
var values = info.split(",");
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
var value = removeWhiteSpace(values[i]);
|
||||
if (value.indexOf("source:") === 0) {
|
||||
processSSESource(elt, value.substr(7));
|
||||
}
|
||||
if (value.indexOf("trigger:") && nodeData.verb) {
|
||||
processSSETrigger(elt, nodeData.verb, nodeData.path, value.substr(8));
|
||||
var value = splitOnWhitespace(values[i]);
|
||||
if (value[0] === "connect") {
|
||||
processSSESource(elt, value[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function processSSESource(elt, sseSrc) {
|
||||
var source = new EventSource(sseSrc, detail.config);
|
||||
var source = htmx.createEventSource(sseSrc);
|
||||
source.onerror = function (e) {
|
||||
triggerErrorEvent(elt, "sseError.htmx", {error:e, source:source});
|
||||
maybeCloseSSESource(elt);
|
||||
@ -769,7 +767,7 @@ return (function () {
|
||||
if (sseSourceElt) {
|
||||
var sseEventSource = getInternalData(sseSourceElt).sseEventSource;
|
||||
var sseListener = function () {
|
||||
if (!maybeCloseSSESource(sseEventSource)) {
|
||||
if (!maybeCloseSSESource(sseSourceElt)) {
|
||||
if (bodyContains(elt)) {
|
||||
issueAjaxRequest(elt, verb, path);
|
||||
} else {
|
||||
@ -807,7 +805,9 @@ return (function () {
|
||||
nodeData.path = path;
|
||||
nodeData.verb = verb;
|
||||
triggerSpecs.forEach(function(triggerSpec) {
|
||||
if (triggerSpec.trigger === "revealed") {
|
||||
if (triggerSpec.sseEvent) {
|
||||
processSSETrigger(elt, verb, path, triggerSpec.sseEvent);
|
||||
} else if (triggerSpec.trigger === "revealed") {
|
||||
initScrollHandler();
|
||||
maybeReveal(elt);
|
||||
} else if (triggerSpec.trigger === "load") {
|
||||
@ -835,13 +835,15 @@ return (function () {
|
||||
if (!explicitAction && getClosestAttributeValue(elt, "hx-boost") === "true") {
|
||||
boostElement(elt, nodeData, triggerSpecs);
|
||||
}
|
||||
|
||||
var sseInfo = getAttributeValue(elt, 'hx-sse');
|
||||
if (sseInfo) {
|
||||
processSSEInfo(elt, nodeData, sseInfo);
|
||||
}
|
||||
var sseInfo = getAttributeValue(elt, 'hx-ws');
|
||||
if (sseInfo) {
|
||||
processWebSocketInfo(elt, nodeData, sseInfo);
|
||||
|
||||
var wsInfo = getAttributeValue(elt, 'hx-ws');
|
||||
if (wsInfo) {
|
||||
processWebSocketInfo(elt, nodeData, wsInfo);
|
||||
}
|
||||
triggerEvent(elt, "processedNode.htmx");
|
||||
}
|
||||
@ -1487,7 +1489,7 @@ return (function () {
|
||||
function getMetaConfig() {
|
||||
var element = getDocument().querySelector('meta[name="htmx-config"]');
|
||||
if (element) {
|
||||
return eval(element.content);
|
||||
return JSON.parse(element.content);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@ -1539,7 +1541,13 @@ return (function () {
|
||||
includeIndicatorStyles:true
|
||||
},
|
||||
parseInterval:parseInterval,
|
||||
_:internalEval
|
||||
_:internalEval,
|
||||
createEventSource: function(url){
|
||||
return new EventSource(url, {withCredentials:true})
|
||||
},
|
||||
createWebSocket: function(url){
|
||||
return new WebSocket(url, []);
|
||||
}
|
||||
}
|
||||
}
|
||||
)()
|
||||
|
2
dist/htmx.min.js
vendored
2
dist/htmx.min.js
vendored
File diff suppressed because one or more lines are too long
BIN
dist/htmx.min.js.gz
vendored
BIN
dist/htmx.min.js.gz
vendored
Binary file not shown.
@ -523,11 +523,10 @@ Htmx offers some officially supported extensions that are tested against the htm
|
||||
| [`json-enc`](/extensions/json-enc) | use JSON encoding in the body of requests, rather than the default `x-www-form-urlencoded`
|
||||
| [`morphdom-swap`](/extensions/morphdom-swap) | an extension for using the [morphdom](https://github.com/patrick-steele-idem/morphdom) library as the swapping mechanism in htmx.
|
||||
| [`client-side-templates`](/extensions/client-side-templates) | support for client side template processing of JSON responses
|
||||
| [`debug`](/extensions/debug) | an extension for debugging of a particular element using htmx
|
||||
| [`path-deps`](/extensions/path-deps) | an extension for expressing path-based dependencies [similar to intercoolerjs](http://intercoolerjs.org/docs.html#dependencies)
|
||||
| [`class-tools`](/extensions/class-tools) | an extension for manipulating timed addition and removal of classes on HTML elements
|
||||
|
||||
See the [references page](/reference#extensions) for a complete list.
|
||||
See the [Extensions](/extensions#list) for a complete list.
|
||||
|
||||
## <a name="events"></a> [Events & Logging](#events)
|
||||
|
||||
|
@ -46,4 +46,17 @@ would say:
|
||||
```
|
||||
|
||||
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.
|
||||
and on the `body` tag for it to apply to all htmx requests.
|
||||
|
||||
## <a name="list"></a> [Extensions Reference](#list)
|
||||
|
||||
The following extensions that are tested and distributed with htmx:
|
||||
|
||||
| Extension | Description
|
||||
|-----------|-------------
|
||||
| [`json-enc`](/extensions/json-enc) | use JSON encoding in the body of requests, rather than the default `x-www-form-urlencoded`
|
||||
| [`morphdom-swap`](/extensions/morphdom-swap) | an extension for using the [morphdom](https://github.com/patrick-steele-idem/morphdom) library as the swapping mechanism in htmx.
|
||||
| [`client-side-templates`](/extensions/client-side-templates) | support for client side template processing of JSON responses
|
||||
| [`debug`](/extensions/debug) | an extension for debugging of a particular element using htmx
|
||||
| [`path-deps`](/extensions/path-deps) | an extension for expressing path-based dependencies [similar to intercoolerjs](http://intercoolerjs.org/docs.html#dependencies)
|
||||
| [`class-tools`](/extensions/class-tools) | an extension for manipulating timed addition and removal of classes on HTML elements
|
||||
|
@ -368,23 +368,26 @@ return (function () {
|
||||
});
|
||||
}
|
||||
|
||||
function handleAttributes(parentNode, fragment, settleInfo) {
|
||||
forEach(fragment.querySelectorAll("[id]"), function (newNode) {
|
||||
var oldNode = parentNode.querySelector(newNode.tagName + "[id=" + newNode.id + "]")
|
||||
if (oldNode && oldNode !== parentNode) {
|
||||
var newAttributes = newNode.cloneNode();
|
||||
cloneAttributes(newNode, oldNode);
|
||||
settleInfo.tasks.push(function () {
|
||||
cloneAttributes(newNode, newAttributes);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function insertNodesBefore(parentNode, insertBefore, fragment, settleInfo) {
|
||||
handleAttributes(parentNode, fragment, settleInfo);
|
||||
while(fragment.childNodes.length > 0){
|
||||
var child = fragment.firstChild;
|
||||
parentNode.insertBefore(child, insertBefore);
|
||||
if (child.nodeType !== Node.TEXT_NODE) {
|
||||
var newAttributes = null;
|
||||
if (child.id) {
|
||||
var originalNode = parentNode.querySelector(child.tagName + "[id=" + child.id + "]");
|
||||
if (originalNode && originalNode !== parentNode) {
|
||||
newAttributes = child.cloneNode();
|
||||
cloneAttributes(child, originalNode);
|
||||
}
|
||||
}
|
||||
settleInfo.tasks.push(function(){
|
||||
if (newAttributes) {
|
||||
cloneAttributes(child, newAttributes);
|
||||
}
|
||||
processNode(child);
|
||||
triggerEvent(child, 'load.htmx', {});
|
||||
});
|
||||
@ -519,6 +522,8 @@ return (function () {
|
||||
|
||||
if (trigger === "every")
|
||||
return {trigger: 'every', pollInterval: parseInterval(tokens[1])};
|
||||
if (trigger.indexOf("sse:") === 0)
|
||||
return {trigger: 'sse', sseEvent: trigger.substr(4)};
|
||||
|
||||
var triggerSpec = {trigger: trigger};
|
||||
for (var i = 1; i < tokens.length; i++) {
|
||||
@ -662,22 +667,18 @@ return (function () {
|
||||
function processWebSocketInfo(elt, nodeData, info) {
|
||||
var values = info.split(",");
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
var value = removeWhiteSpace(values[i]);
|
||||
if (value.indexOf("source:") === 0) {
|
||||
processWebSocketSource(elt, value.substr(7));
|
||||
var value = splitOnWhitespace(values[i]);
|
||||
if (value[0] === "connect") {
|
||||
processWebSocketSource(elt, value[1]);
|
||||
}
|
||||
if (value.indexOf("send:") === 0) {
|
||||
processWebSocketSend(elt, value.substr(5));
|
||||
if (value[0] === "send") {
|
||||
processWebSocketSend(elt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function processWebSocketSource(elt, wssSource) {
|
||||
var detail = {
|
||||
protocols:[]
|
||||
};
|
||||
triggerEvent(elt, "initWebSocket.htmx", detail);
|
||||
var socket = new WebSocket("wss:" + wssSource, detail.protocols);
|
||||
var socket = htmx.createWebSocket(wssSource);
|
||||
socket.onerror = function (e) {
|
||||
triggerErrorEvent(elt, "wsError.htmx", {error:e, socket:socket});
|
||||
maybeCloseWebSocketSource(elt);
|
||||
@ -712,13 +713,13 @@ return (function () {
|
||||
}
|
||||
}
|
||||
|
||||
function processWebSocketSend(elt, eventName) {
|
||||
function processWebSocketSend(elt) {
|
||||
var webSocketSourceElt = getClosestMatch(elt, function (parent) {
|
||||
return getInternalData(parent).webSocket != null;
|
||||
});
|
||||
if (webSocketSourceElt) {
|
||||
var webSocket = getInternalData(webSocketSourceElt).webSocket;
|
||||
elt.addEventListener(eventName, function (evt) {
|
||||
elt.addEventListener(getTriggerSpecs(elt)[0].trigger, function (evt) {
|
||||
var headers = getHeaders(elt, webSocketSourceElt, null, elt);
|
||||
var rawParameters = getInputValues(elt, 'post');
|
||||
var filteredParameters = filterValues(rawParameters, elt);
|
||||
@ -743,18 +744,15 @@ return (function () {
|
||||
function processSSEInfo(elt, nodeData, info) {
|
||||
var values = info.split(",");
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
var value = removeWhiteSpace(values[i]);
|
||||
if (value.indexOf("source:") === 0) {
|
||||
processSSESource(elt, value.substr(7));
|
||||
}
|
||||
if (value.indexOf("trigger:") && nodeData.verb) {
|
||||
processSSETrigger(elt, nodeData.verb, nodeData.path, value.substr(8));
|
||||
var value = splitOnWhitespace(values[i]);
|
||||
if (value[0] === "connect") {
|
||||
processSSESource(elt, value[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function processSSESource(elt, sseSrc) {
|
||||
var source = new EventSource(sseSrc, detail.config);
|
||||
var source = htmx.createEventSource(sseSrc);
|
||||
source.onerror = function (e) {
|
||||
triggerErrorEvent(elt, "sseError.htmx", {error:e, source:source});
|
||||
maybeCloseSSESource(elt);
|
||||
@ -769,7 +767,7 @@ return (function () {
|
||||
if (sseSourceElt) {
|
||||
var sseEventSource = getInternalData(sseSourceElt).sseEventSource;
|
||||
var sseListener = function () {
|
||||
if (!maybeCloseSSESource(sseEventSource)) {
|
||||
if (!maybeCloseSSESource(sseSourceElt)) {
|
||||
if (bodyContains(elt)) {
|
||||
issueAjaxRequest(elt, verb, path);
|
||||
} else {
|
||||
@ -807,7 +805,9 @@ return (function () {
|
||||
nodeData.path = path;
|
||||
nodeData.verb = verb;
|
||||
triggerSpecs.forEach(function(triggerSpec) {
|
||||
if (triggerSpec.trigger === "revealed") {
|
||||
if (triggerSpec.sseEvent) {
|
||||
processSSETrigger(elt, verb, path, triggerSpec.sseEvent);
|
||||
} else if (triggerSpec.trigger === "revealed") {
|
||||
initScrollHandler();
|
||||
maybeReveal(elt);
|
||||
} else if (triggerSpec.trigger === "load") {
|
||||
@ -835,13 +835,15 @@ return (function () {
|
||||
if (!explicitAction && getClosestAttributeValue(elt, "hx-boost") === "true") {
|
||||
boostElement(elt, nodeData, triggerSpecs);
|
||||
}
|
||||
|
||||
var sseInfo = getAttributeValue(elt, 'hx-sse');
|
||||
if (sseInfo) {
|
||||
processSSEInfo(elt, nodeData, sseInfo);
|
||||
}
|
||||
var sseInfo = getAttributeValue(elt, 'hx-ws');
|
||||
if (sseInfo) {
|
||||
processWebSocketInfo(elt, nodeData, sseInfo);
|
||||
|
||||
var wsInfo = getAttributeValue(elt, 'hx-ws');
|
||||
if (wsInfo) {
|
||||
processWebSocketInfo(elt, nodeData, wsInfo);
|
||||
}
|
||||
triggerEvent(elt, "processedNode.htmx");
|
||||
}
|
||||
@ -1487,7 +1489,7 @@ return (function () {
|
||||
function getMetaConfig() {
|
||||
var element = getDocument().querySelector('meta[name="htmx-config"]');
|
||||
if (element) {
|
||||
return eval(element.content);
|
||||
return JSON.parse(element.content);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@ -1539,7 +1541,13 @@ return (function () {
|
||||
includeIndicatorStyles:true
|
||||
},
|
||||
parseInterval:parseInterval,
|
||||
_:internalEval
|
||||
_:internalEval,
|
||||
createEventSource: function(url){
|
||||
return new EventSource(url, {withCredentials:true})
|
||||
},
|
||||
createWebSocket: function(url){
|
||||
return new WebSocket(url, []);
|
||||
}
|
||||
}
|
||||
}
|
||||
)()
|
||||
|
@ -93,13 +93,3 @@ title: </> htmx - Attributes
|
||||
| [`swapError.htmx`](/events#swapError.htmx) | triggered when an error occurs during the swap phase
|
||||
| [`targetError.htmx`](/events#targetError.htmx) | triggered when an invalid target is specified
|
||||
|
||||
## <a name="extensions"></a> [Extensions Reference](#extensions)
|
||||
|
||||
| Extension | Description
|
||||
|-----------|-------------
|
||||
| [`json-enc`](/extensions/json-enc) | use JSON encoding in the body of requests, rather than the default `x-www-form-urlencoded`
|
||||
| [`morphdom-swap`](/extensions/morphdom-swap) | an extension for using the [morphdom](https://github.com/patrick-steele-idem/morphdom) library as the swapping mechanism in htmx.
|
||||
| [`client-side-templates`](/extensions/client-side-templates) | support for client side template processing of JSON responses
|
||||
| [`debug`](/extensions/debug) | an extension for debugging of a particular element using htmx
|
||||
| [`path-deps`](/extensions/path-deps) | an extension for expressing path-based dependencies [similar to intercoolerjs](http://intercoolerjs.org/docs.html#dependencies)
|
||||
| [`class-tools`](/extensions/class-tools) | an extension for manipulating timed addition and removal of classes on HTML elements
|
||||
|
@ -368,23 +368,26 @@ return (function () {
|
||||
});
|
||||
}
|
||||
|
||||
function handleAttributes(parentNode, fragment, settleInfo) {
|
||||
forEach(fragment.querySelectorAll("[id]"), function (newNode) {
|
||||
var oldNode = parentNode.querySelector(newNode.tagName + "[id=" + newNode.id + "]")
|
||||
if (oldNode && oldNode !== parentNode) {
|
||||
var newAttributes = newNode.cloneNode();
|
||||
cloneAttributes(newNode, oldNode);
|
||||
settleInfo.tasks.push(function () {
|
||||
cloneAttributes(newNode, newAttributes);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function insertNodesBefore(parentNode, insertBefore, fragment, settleInfo) {
|
||||
handleAttributes(parentNode, fragment, settleInfo);
|
||||
while(fragment.childNodes.length > 0){
|
||||
var child = fragment.firstChild;
|
||||
parentNode.insertBefore(child, insertBefore);
|
||||
if (child.nodeType !== Node.TEXT_NODE) {
|
||||
var newAttributes = null;
|
||||
if (child.id) {
|
||||
var originalNode = parentNode.querySelector(child.tagName + "[id=" + child.id + "]");
|
||||
if (originalNode && originalNode !== parentNode) {
|
||||
newAttributes = child.cloneNode();
|
||||
cloneAttributes(child, originalNode);
|
||||
}
|
||||
}
|
||||
settleInfo.tasks.push(function(){
|
||||
if (newAttributes) {
|
||||
cloneAttributes(child, newAttributes);
|
||||
}
|
||||
processNode(child);
|
||||
triggerEvent(child, 'load.htmx', {});
|
||||
});
|
||||
@ -519,6 +522,8 @@ return (function () {
|
||||
|
||||
if (trigger === "every")
|
||||
return {trigger: 'every', pollInterval: parseInterval(tokens[1])};
|
||||
if (trigger.indexOf("sse:") === 0)
|
||||
return {trigger: 'sse', sseEvent: trigger.substr(4)};
|
||||
|
||||
var triggerSpec = {trigger: trigger};
|
||||
for (var i = 1; i < tokens.length; i++) {
|
||||
@ -662,22 +667,18 @@ return (function () {
|
||||
function processWebSocketInfo(elt, nodeData, info) {
|
||||
var values = info.split(",");
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
var value = removeWhiteSpace(values[i]);
|
||||
if (value.indexOf("source:") === 0) {
|
||||
processWebSocketSource(elt, value.substr(7));
|
||||
var value = splitOnWhitespace(values[i]);
|
||||
if (value[0] === "connect") {
|
||||
processWebSocketSource(elt, value[1]);
|
||||
}
|
||||
if (value.indexOf("send:") === 0) {
|
||||
processWebSocketSend(elt, value.substr(5));
|
||||
if (value[0] === "send") {
|
||||
processWebSocketSend(elt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function processWebSocketSource(elt, wssSource) {
|
||||
var detail = {
|
||||
protocols:[]
|
||||
};
|
||||
triggerEvent(elt, "initWebSocket.htmx", detail);
|
||||
var socket = new WebSocket("wss:" + wssSource, detail.protocols);
|
||||
var socket = htmx.createWebSocket(wssSource);
|
||||
socket.onerror = function (e) {
|
||||
triggerErrorEvent(elt, "wsError.htmx", {error:e, socket:socket});
|
||||
maybeCloseWebSocketSource(elt);
|
||||
@ -712,13 +713,13 @@ return (function () {
|
||||
}
|
||||
}
|
||||
|
||||
function processWebSocketSend(elt, eventName) {
|
||||
function processWebSocketSend(elt) {
|
||||
var webSocketSourceElt = getClosestMatch(elt, function (parent) {
|
||||
return getInternalData(parent).webSocket != null;
|
||||
});
|
||||
if (webSocketSourceElt) {
|
||||
var webSocket = getInternalData(webSocketSourceElt).webSocket;
|
||||
elt.addEventListener(eventName, function (evt) {
|
||||
elt.addEventListener(getTriggerSpecs(elt)[0].trigger, function (evt) {
|
||||
var headers = getHeaders(elt, webSocketSourceElt, null, elt);
|
||||
var rawParameters = getInputValues(elt, 'post');
|
||||
var filteredParameters = filterValues(rawParameters, elt);
|
||||
@ -743,18 +744,15 @@ return (function () {
|
||||
function processSSEInfo(elt, nodeData, info) {
|
||||
var values = info.split(",");
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
var value = removeWhiteSpace(values[i]);
|
||||
if (value.indexOf("source:") === 0) {
|
||||
processSSESource(elt, value.substr(7));
|
||||
}
|
||||
if (value.indexOf("trigger:") && nodeData.verb) {
|
||||
processSSETrigger(elt, nodeData.verb, nodeData.path, value.substr(8));
|
||||
var value = splitOnWhitespace(values[i]);
|
||||
if (value[0] === "connect") {
|
||||
processSSESource(elt, value[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function processSSESource(elt, sseSrc) {
|
||||
var source = new EventSource(sseSrc, detail.config);
|
||||
var source = htmx.createEventSource(sseSrc);
|
||||
source.onerror = function (e) {
|
||||
triggerErrorEvent(elt, "sseError.htmx", {error:e, source:source});
|
||||
maybeCloseSSESource(elt);
|
||||
@ -769,7 +767,7 @@ return (function () {
|
||||
if (sseSourceElt) {
|
||||
var sseEventSource = getInternalData(sseSourceElt).sseEventSource;
|
||||
var sseListener = function () {
|
||||
if (!maybeCloseSSESource(sseEventSource)) {
|
||||
if (!maybeCloseSSESource(sseSourceElt)) {
|
||||
if (bodyContains(elt)) {
|
||||
issueAjaxRequest(elt, verb, path);
|
||||
} else {
|
||||
@ -807,7 +805,9 @@ return (function () {
|
||||
nodeData.path = path;
|
||||
nodeData.verb = verb;
|
||||
triggerSpecs.forEach(function(triggerSpec) {
|
||||
if (triggerSpec.trigger === "revealed") {
|
||||
if (triggerSpec.sseEvent) {
|
||||
processSSETrigger(elt, verb, path, triggerSpec.sseEvent);
|
||||
} else if (triggerSpec.trigger === "revealed") {
|
||||
initScrollHandler();
|
||||
maybeReveal(elt);
|
||||
} else if (triggerSpec.trigger === "load") {
|
||||
@ -835,13 +835,15 @@ return (function () {
|
||||
if (!explicitAction && getClosestAttributeValue(elt, "hx-boost") === "true") {
|
||||
boostElement(elt, nodeData, triggerSpecs);
|
||||
}
|
||||
|
||||
var sseInfo = getAttributeValue(elt, 'hx-sse');
|
||||
if (sseInfo) {
|
||||
processSSEInfo(elt, nodeData, sseInfo);
|
||||
}
|
||||
var sseInfo = getAttributeValue(elt, 'hx-ws');
|
||||
if (sseInfo) {
|
||||
processWebSocketInfo(elt, nodeData, sseInfo);
|
||||
|
||||
var wsInfo = getAttributeValue(elt, 'hx-ws');
|
||||
if (wsInfo) {
|
||||
processWebSocketInfo(elt, nodeData, wsInfo);
|
||||
}
|
||||
triggerEvent(elt, "processedNode.htmx");
|
||||
}
|
||||
@ -1487,7 +1489,7 @@ return (function () {
|
||||
function getMetaConfig() {
|
||||
var element = getDocument().querySelector('meta[name="htmx-config"]');
|
||||
if (element) {
|
||||
return eval(element.content);
|
||||
return JSON.parse(element.content);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@ -1539,7 +1541,13 @@ return (function () {
|
||||
includeIndicatorStyles:true
|
||||
},
|
||||
parseInterval:parseInterval,
|
||||
_:internalEval
|
||||
_:internalEval,
|
||||
createEventSource: function(url){
|
||||
return new EventSource(url, {withCredentials:true})
|
||||
},
|
||||
createWebSocket: function(url){
|
||||
return new WebSocket(url, []);
|
||||
}
|
||||
}
|
||||
}
|
||||
)()
|
||||
|
95
www/test/0.0.4/test/attributes/hx-sse.js
Normal file
95
www/test/0.0.4/test/attributes/hx-sse.js
Normal file
@ -0,0 +1,95 @@
|
||||
describe("hx-sse attribute", function() {
|
||||
|
||||
function mockEventSource() {
|
||||
var listeners = {};
|
||||
var mockEventSource = {
|
||||
addEventListener : function(message, l) {
|
||||
listeners[message] = l;
|
||||
},
|
||||
sendEvent : function(event) {
|
||||
var listener = listeners[event];
|
||||
if(listener){
|
||||
listener();
|
||||
}
|
||||
},
|
||||
};
|
||||
return mockEventSource;
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
this.server = makeServer();
|
||||
var eventSource = mockEventSource();
|
||||
this.eventSource = eventSource;
|
||||
clearWorkArea();
|
||||
htmx.createEventSource = function(){ return eventSource };
|
||||
});
|
||||
afterEach(function () {
|
||||
this.server.restore();
|
||||
clearWorkArea();
|
||||
});
|
||||
|
||||
it('handles basic sse triggering', function () {
|
||||
|
||||
this.server.respondWith("GET", "/d1", "div1 updated");
|
||||
this.server.respondWith("GET", "/d2", "div2 updated");
|
||||
|
||||
var div = make('<div hx-sse="connect /foo">' +
|
||||
'<div id="d1" hx-trigger="sse:e1" hx-get="/d1">div1</div>' +
|
||||
'<div id="d2" hx-trigger="sse:e2" hx-get="/d2">div2</div>' +
|
||||
'</div>');
|
||||
|
||||
this.eventSource.sendEvent("e1");
|
||||
this.server.respond();
|
||||
byId("d1").innerHTML.should.equal("div1 updated");
|
||||
byId("d2").innerHTML.should.equal("div2");
|
||||
|
||||
this.eventSource.sendEvent("e2");
|
||||
this.server.respond();
|
||||
byId("d1").innerHTML.should.equal("div1 updated");
|
||||
byId("d2").innerHTML.should.equal("div2 updated");
|
||||
})
|
||||
|
||||
it('does not trigger events that arent named', function () {
|
||||
|
||||
this.server.respondWith("GET", "/d1", "div1 updated");
|
||||
|
||||
var div = make('<div hx-sse="connect /foo">' +
|
||||
'<div id="d1" hx-trigger="sse:e1" hx-get="/d1">div1</div>' +
|
||||
'</div>');
|
||||
|
||||
this.eventSource.sendEvent("foo");
|
||||
this.server.respond();
|
||||
byId("d1").innerHTML.should.equal("div1");
|
||||
|
||||
this.eventSource.sendEvent("e2");
|
||||
this.server.respond();
|
||||
byId("d1").innerHTML.should.equal("div1");
|
||||
|
||||
this.eventSource.sendEvent("e1");
|
||||
this.server.respond();
|
||||
byId("d1").innerHTML.should.equal("div1 updated");
|
||||
})
|
||||
|
||||
it('does not trigger events not on decendents', function () {
|
||||
|
||||
this.server.respondWith("GET", "/d1", "div1 updated");
|
||||
|
||||
var div = make('<div hx-sse="connect /foo"></div>' +
|
||||
'<div id="d1" hx-trigger="sse:e1" hx-get="/d1">div1</div>');
|
||||
|
||||
this.eventSource.sendEvent("foo");
|
||||
this.server.respond();
|
||||
byId("d1").innerHTML.should.equal("div1");
|
||||
|
||||
this.eventSource.sendEvent("e2");
|
||||
this.server.respond();
|
||||
byId("d1").innerHTML.should.equal("div1");
|
||||
|
||||
this.eventSource.sendEvent("e1");
|
||||
this.server.respond();
|
||||
byId("d1").innerHTML.should.equal("div1");
|
||||
})
|
||||
|
||||
|
||||
});
|
||||
|
51
www/test/0.0.4/test/attributes/hx-ws.js
Normal file
51
www/test/0.0.4/test/attributes/hx-ws.js
Normal file
@ -0,0 +1,51 @@
|
||||
describe("hx-ws attribute", function() {
|
||||
|
||||
function mockWebsocket() {
|
||||
var listener;
|
||||
var lastSent;
|
||||
var mockSocket = {
|
||||
addEventListener : function(message, l) {
|
||||
listener = l;
|
||||
},
|
||||
write : function(content) {
|
||||
return listener({data:content});
|
||||
},
|
||||
send : function(data) {
|
||||
lastSent = data;
|
||||
},
|
||||
getLastSent : function() {
|
||||
return lastSent;
|
||||
}
|
||||
};
|
||||
return mockSocket;
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
this.server = makeServer();
|
||||
var socket = mockWebsocket();
|
||||
this.socket = socket;
|
||||
clearWorkArea();
|
||||
htmx.createWebSocket = function(){ return socket };
|
||||
});
|
||||
afterEach(function () {
|
||||
this.server.restore();
|
||||
clearWorkArea();
|
||||
});
|
||||
|
||||
it('handles a basic call back', function () {
|
||||
var div = make('<div hx-ws="connect wss:/foo"><div id="d1">div1</div><div id="d2">div2</div></div>');
|
||||
this.socket.write("<div id=\"d1\">replaced</div>")
|
||||
byId("d1").innerHTML.should.equal("replaced");
|
||||
byId("d2").innerHTML.should.equal("div2");
|
||||
})
|
||||
|
||||
it('handles a basic send', function () {
|
||||
var div = make('<div hx-ws="connect wss:/foo"><div hx-ws="send" id="d1">div1</div></div>');
|
||||
byId("d1").click();
|
||||
var lastSent = this.socket.getLastSent();
|
||||
var data = JSON.parse(lastSent);
|
||||
data.HEADERS["X-HX-Request"].should.equal("true");
|
||||
})
|
||||
|
||||
});
|
||||
|
@ -305,6 +305,19 @@ describe("Core htmx AJAX Tests", function(){
|
||||
div.innerHTML.should.equal("<div id=\"d1\">foo</div>");
|
||||
});
|
||||
|
||||
it('properly settles attributes on interior elements', function(done)
|
||||
{
|
||||
this.server.respondWith("GET", "/test", "<div hx-get='/test'><div foo='bar' id='d1'></div></div>");
|
||||
var div = make("<div hx-get='/test' hx-swap='outerHTML settle:10ms'><div id='d1'></div></div>");
|
||||
div.click();
|
||||
this.server.respond();
|
||||
should.equal(byId("d1").getAttribute("foo"), null);
|
||||
setTimeout(function () {
|
||||
should.equal(byId("d1").getAttribute("foo"), "bar");
|
||||
done();
|
||||
}, 20);
|
||||
});
|
||||
|
||||
it('properly handles checkbox inputs', function()
|
||||
{
|
||||
var values;
|
||||
|
@ -74,10 +74,13 @@
|
||||
<script src="attributes/hx-post.js"></script>
|
||||
<script src="attributes/hx-push-url.js"></script>
|
||||
<script src="attributes/hx-put.js"></script>
|
||||
<script src="attributes/hx-select.js"></script>
|
||||
<script src="attributes/hx-sse.js"></script>
|
||||
<script src="attributes/hx-swap-oob.js"></script>
|
||||
<script src="attributes/hx-swap.js"></script>
|
||||
<script src="attributes/hx-target.js"></script>
|
||||
<script src="attributes/hx-trigger.js"></script>
|
||||
<script src="attributes/hx-ws.js"></script>
|
||||
|
||||
<!-- extension tests -->
|
||||
<script src="../src/ext/rails-method.js"></script>
|
||||
|
Loading…
x
Reference in New Issue
Block a user