mirror of
https://github.com/bigskysoftware/htmx.git
synced 2026-04-19 13:26:23 +00:00
le big rename
This commit is contained in:
13
README.md
13
README.md
@@ -1,12 +1,9 @@
|
||||
# </> HTMx
|
||||
HTML Extensions
|
||||
# </> kutty
|
||||
*High power tools for HTML*
|
||||
|
||||
## Overview
|
||||
|
||||
HTMx allows you to issue AJAX requests from HTML without needing to write any javascript. It is a set of extensions
|
||||
to HTML (attributes, request headers, etc.) that allow you to use markup for more complex user interfaces and
|
||||
features, while at the same time retaining the simplicity of the original web programming model.
|
||||
Kutty is a set of HTML extensions (attributes, request headers, etc.) that allow you to use markup for complex user
|
||||
interfaces and features, while retaining the simplicity and power of the hypertext we all know and love.
|
||||
|
||||
## Background
|
||||
|
||||
HTMx is inspired by [intercooler.js](http://intercoolerjs.org), but aims to simplify that library and include no dependencies.
|
||||
Kutty is the successor to [intercooler.js](http://intercoolerjs.org)
|
||||
19
TODO.md
19
TODO.md
@@ -1,14 +1,8 @@
|
||||
# </> HTMx
|
||||
*HTML Extensions*
|
||||
|
||||
## GOALS
|
||||
|
||||
* Dependency-free implementation of intercooler.js-like HTML-driven AJAX functionality
|
||||
* Minimalist functionality, rely heavily on built in functionality
|
||||
* Support IE10+
|
||||
** CSS transitions only
|
||||
** Pluggable event model
|
||||
* < 10k in .min form
|
||||
* Dependency-free implementation of intercooler.js
|
||||
* Support IE11 (stretch: IE10)
|
||||
* < 10k in .min.gz form
|
||||
|
||||
## TODOS
|
||||
|
||||
@@ -21,9 +15,9 @@
|
||||
* Testing
|
||||
* polling
|
||||
* merge
|
||||
* hx-select
|
||||
* kt-select
|
||||
* history
|
||||
* hx-boost
|
||||
* kt-boost
|
||||
* transition model for content swaps
|
||||
* build website with 11ty
|
||||
* landing page
|
||||
@@ -47,5 +41,4 @@
|
||||
* http://youmightnotneedjquery.com/
|
||||
* http://intercoolerjs.org/docs.html
|
||||
* http://intercoolerjs.org/reference.html
|
||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap
|
||||
|
||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap
|
||||
1996
package-lock.json
generated
1996
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
26
package.json
26
package.json
@@ -1,15 +1,14 @@
|
||||
{
|
||||
"name": "htmx.org",
|
||||
"description": "HTML Extensions",
|
||||
"name": "kutty.org",
|
||||
"description": "high power tools for html",
|
||||
"keywords": [
|
||||
"htmx",
|
||||
"AJAX",
|
||||
"HTML"
|
||||
],
|
||||
"version": "0.0.2",
|
||||
"homepage": "https://htmx.org/",
|
||||
"version": "0.0.1",
|
||||
"homepage": "https://kutty.org/",
|
||||
"bugs": {
|
||||
"url": "https://github.com/bigskysoftware/htmx/issues"
|
||||
"url": "https://github.com/bigskysoftware/kutty/issues"
|
||||
},
|
||||
"license": "BSD 2-Clause",
|
||||
"files": [
|
||||
@@ -17,26 +16,27 @@
|
||||
"README.md",
|
||||
"dist/*.js"
|
||||
],
|
||||
"main": "dist/htmx.min.js",
|
||||
"unpkg": "dist/htmx.min.js",
|
||||
"main": "dist/kutty.min.js",
|
||||
"unpkg": "dist/kutty.min.js",
|
||||
"scripts": {
|
||||
"test": "mocha-chrome test/index.html",
|
||||
"dist": "cp src/htmx.js dist/ && npm run-script uglify && gzip -k -f dist/htmx.min.js > dist/htmx.min.js.gz && exit",
|
||||
"dist": "cp src/cutty.js dist/ && npm run-script uglify && gzip -k -f dist/cutty.min.js > dist/kutty.min.js.gz && exit",
|
||||
"www": "node scripts/www.js",
|
||||
"uglify": "uglifyjs -m eval -o dist/htmx.min.js dist/htmx.js"
|
||||
"uglify": "uglifyjs -m eval -o dist/kutty.min.js dist/kutty.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/bigskysoftware/htmx.git"
|
||||
"url": "git+https://github.com/bigskysoftware/kutty.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@11ty/eleventy": "^0.10.0",
|
||||
"@11ty/eleventy-plugin-syntaxhighlight": "^3.0.1",
|
||||
"chai": "^4.2.0",
|
||||
"eleventy-plugin-sass": "^1.0.0",
|
||||
"fs-extra": "^9.0.0",
|
||||
"mocha": "^7.1.1",
|
||||
"mocha-chrome": "^2.2.0",
|
||||
"sinon": "^9.0.2",
|
||||
"uglify-js": "^3.9.1",
|
||||
"fs-extra": "^9.0.0"
|
||||
"uglify-js": "^3.9.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// noinspection JSUnusedAssignment
|
||||
var HTMx = HTMx || (function () {
|
||||
var kutty = kutty || (function () {
|
||||
'use strict';
|
||||
|
||||
var VERBS = ['get', 'post', 'put', 'delete', 'patch']
|
||||
@@ -24,7 +24,7 @@ var HTMx = HTMx || (function () {
|
||||
return elt.getAttribute && elt.getAttribute(name);
|
||||
}
|
||||
|
||||
// resolve with both hx and data-hx prefixes
|
||||
// resolve with both kt and data-kt prefixes
|
||||
function getAttributeValue(elt, qualifiedName) {
|
||||
return getRawAttribute(elt, qualifiedName) || getRawAttribute(elt, "data-" + qualifiedName);
|
||||
}
|
||||
@@ -87,7 +87,7 @@ var HTMx = HTMx || (function () {
|
||||
}
|
||||
|
||||
function getInternalData(elt) {
|
||||
var dataProp = 'hx-data-internal';
|
||||
var dataProp = 'kutty-internal-data';
|
||||
var data = elt[dataProp];
|
||||
if (!data) {
|
||||
data = elt[dataProp] = {};
|
||||
@@ -129,9 +129,9 @@ var HTMx = HTMx || (function () {
|
||||
//====================================================================
|
||||
|
||||
function getTarget(elt) {
|
||||
var explicitTarget = getClosestMatch(elt, function(e){return getRawAttribute(e,"hx-target") !== null});
|
||||
var explicitTarget = getClosestMatch(elt, function(e){return getRawAttribute(e,"kt-target") !== null});
|
||||
if (explicitTarget) {
|
||||
var targetStr = getRawAttribute(explicitTarget, "hx-target");
|
||||
var targetStr = getRawAttribute(explicitTarget, "kt-target");
|
||||
if (targetStr === "this") {
|
||||
return explicitTarget;
|
||||
} else {
|
||||
@@ -161,7 +161,7 @@ var HTMx = HTMx || (function () {
|
||||
function handleOutOfBandSwaps(fragment) {
|
||||
var settleTasks = [];
|
||||
forEach(fragment.children, function(child){
|
||||
if (getAttributeValue(child, "hx-swap-oob") === "true") {
|
||||
if (getAttributeValue(child, "kt-swap-oob") === "true") {
|
||||
var target = getDocument().getElementById(child.id);
|
||||
if (target) {
|
||||
var fragment = new DocumentFragment()
|
||||
@@ -169,7 +169,7 @@ var HTMx = HTMx || (function () {
|
||||
settleTasks = settleTasks.concat(swapOuterHTML(target, fragment));
|
||||
} else {
|
||||
child.parentNode.removeChild(child);
|
||||
triggerEvent(getDocument().body, "oobErrorNoTarget.hx", {id:child.id, content:child})
|
||||
triggerEvent(getDocument().body, "oobErrorNoTarget.kutty", {id:child.id, content:child})
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -197,7 +197,7 @@ var HTMx = HTMx || (function () {
|
||||
var child = fragment.firstChild;
|
||||
parentNode.insertBefore(child, insertBefore);
|
||||
if (child.nodeType !== Node.TEXT_NODE) {
|
||||
triggerEvent(child, 'load.hx', {elt:child, parent:parentElt(child)});
|
||||
triggerEvent(child, 'load.kutty', {elt:child, parent:parentElt(child)});
|
||||
processNode(child);
|
||||
}
|
||||
}
|
||||
@@ -243,7 +243,7 @@ var HTMx = HTMx || (function () {
|
||||
}
|
||||
|
||||
function maybeSelectFromResponse(elt, fragment) {
|
||||
var selector = getClosestAttributeValue(elt, "hx-select");
|
||||
var selector = getClosestAttributeValue(elt, "kt-select");
|
||||
if (selector) {
|
||||
var newFragment = new DocumentFragment();
|
||||
forEach(fragment.querySelectorAll(selector), function (node) {
|
||||
@@ -260,7 +260,7 @@ var HTMx = HTMx || (function () {
|
||||
|
||||
fragment = maybeSelectFromResponse(elt, fragment);
|
||||
|
||||
var swapStyle = getClosestAttributeValue(elt, "hx-swap");
|
||||
var swapStyle = getClosestAttributeValue(elt, "kt-swap");
|
||||
switch(swapStyle) {
|
||||
case "outerHTML": return concat(settleTasks, swapOuterHTML(target, fragment));
|
||||
case "prepend": return concat(settleTasks, swapPrepend(target, fragment));
|
||||
@@ -291,7 +291,7 @@ var HTMx = HTMx || (function () {
|
||||
}
|
||||
|
||||
function getTrigger(elt) {
|
||||
var explicitTrigger = getClosestAttributeValue(elt, 'hx-trigger');
|
||||
var explicitTrigger = getClosestAttributeValue(elt, 'kt-trigger');
|
||||
if (explicitTrigger) {
|
||||
return explicitTrigger;
|
||||
} else {
|
||||
@@ -337,7 +337,7 @@ var HTMx = HTMx || (function () {
|
||||
nodeData.timeout = setTimeout(function () {
|
||||
if (bodyContains(elt)) {
|
||||
issueAjaxRequest(elt, verb, path);
|
||||
processPolling(elt, verb, getAttributeValue(elt, "hx-" + verb));
|
||||
processPolling(elt, verb, getAttributeValue(elt, "kt-" + verb));
|
||||
}
|
||||
}, interval);
|
||||
}
|
||||
@@ -373,14 +373,14 @@ var HTMx = HTMx || (function () {
|
||||
var elementData = getInternalData(elt);
|
||||
if (!eventData.handled) {
|
||||
eventData.handled = true;
|
||||
if (getAttributeValue(elt, "hx-trigger-once") === "true") {
|
||||
if (getAttributeValue(elt, "kt-trigger-once") === "true") {
|
||||
if (elementData.triggeredOnce) {
|
||||
return;
|
||||
} else {
|
||||
elementData.triggeredOnce = true;
|
||||
}
|
||||
}
|
||||
if (getAttributeValue(elt, "hx-trigger-changed-only") === "true") {
|
||||
if (getAttributeValue(elt, "kt-trigger-changed-only") === "true") {
|
||||
if (elementData.lastValue === elt.value) {
|
||||
return;
|
||||
} else {
|
||||
@@ -390,7 +390,7 @@ var HTMx = HTMx || (function () {
|
||||
if (elementData.delayed) {
|
||||
clearTimeout(elementData.delayed);
|
||||
}
|
||||
var eventDelay = getAttributeValue(elt, "hx-trigger-delay");
|
||||
var eventDelay = getAttributeValue(elt, "kt-trigger-delay");
|
||||
var issueRequest = function(){
|
||||
issueAjaxRequest(elt, verb, path, evt.target);
|
||||
}
|
||||
@@ -407,13 +407,13 @@ var HTMx = HTMx || (function () {
|
||||
}
|
||||
|
||||
function initScrollHandler() {
|
||||
if (!window['hxScrollHandler']) {
|
||||
if (!window['kuttyScrollHandler']) {
|
||||
var scrollHandler = function() {
|
||||
forEach(getDocument().querySelectorAll("[hx-trigger='reveal']"), function (elt) {
|
||||
forEach(getDocument().querySelectorAll("[kt-trigger='reveal']"), function (elt) {
|
||||
maybeReveal(elt);
|
||||
});
|
||||
};
|
||||
window['hxScrollHandler'] = scrollHandler;
|
||||
window['kuttyScrollHandler'] = scrollHandler;
|
||||
window.addEventListener("scroll", scrollHandler)
|
||||
}
|
||||
}
|
||||
@@ -438,10 +438,10 @@ var HTMx = HTMx || (function () {
|
||||
initializer: function() { new EventSource(sseSrc, details.config) },
|
||||
config:{withCredentials: true}
|
||||
};
|
||||
triggerEvent(elt, "initSSE.mx", {config:details})
|
||||
triggerEvent(elt, "initSSE.kutty", {config:details})
|
||||
var source = details.initializer();
|
||||
source.onerror = function (e) {
|
||||
triggerEvent(elt, "sseError.mx", {error:e, source:source});
|
||||
triggerEvent(elt, "sseError.kutty", {error:e, source:source});
|
||||
maybeCloseSSESource(elt);
|
||||
};
|
||||
getInternalData(elt).sseSource = source;
|
||||
@@ -463,7 +463,7 @@ var HTMx = HTMx || (function () {
|
||||
};
|
||||
sseSource.sseSource.addEventListener(sseEventName, sseListener);
|
||||
} else {
|
||||
triggerEvent(elt, "noSSESourceError.mx")
|
||||
triggerEvent(elt, "noSSESourceError.kutty")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -477,7 +477,7 @@ var HTMx = HTMx || (function () {
|
||||
function processVerbs(elt, nodeData, trigger) {
|
||||
var explicitAction = false;
|
||||
forEach(VERBS, function (verb) {
|
||||
var path = getAttributeValue(elt, 'hx-' + verb);
|
||||
var path = getAttributeValue(elt, 'kt-' + verb);
|
||||
if (path) {
|
||||
explicitAction = true;
|
||||
nodeData.path = path;
|
||||
@@ -508,18 +508,18 @@ var HTMx = HTMx || (function () {
|
||||
var trigger = getTrigger(elt);
|
||||
var explicitAction = processVerbs(elt, nodeData, trigger);
|
||||
|
||||
if (!explicitAction && getClosestAttributeValue(elt, "hx-boost") === "true") {
|
||||
if (!explicitAction && getClosestAttributeValue(elt, "kt-boost") === "true") {
|
||||
boostElement(elt, nodeData, trigger);
|
||||
}
|
||||
var sseSrc = getAttributeValue(elt, 'hx-sse-source');
|
||||
var sseSrc = getAttributeValue(elt, 'kt-sse-source');
|
||||
if (sseSrc) {
|
||||
initSSESource(elt, sseSrc);
|
||||
}
|
||||
var addClass = getAttributeValue(elt, 'hx-add-class');
|
||||
var addClass = getAttributeValue(elt, 'kt-add-class');
|
||||
if (addClass) {
|
||||
processClassList(elt, addClass, "add");
|
||||
}
|
||||
var removeClass = getAttributeValue(elt, 'hx-remove-class');
|
||||
var removeClass = getAttributeValue(elt, 'kt-remove-class');
|
||||
if (removeClass) {
|
||||
processClassList(elt, removeClass, "remove");
|
||||
}
|
||||
@@ -532,7 +532,7 @@ var HTMx = HTMx || (function () {
|
||||
//====================================================================
|
||||
|
||||
function sendError(elt, eventName, details) {
|
||||
var errorURL = getClosestAttributeValue(elt, "hx-error-url");
|
||||
var errorURL = getClosestAttributeValue(elt, "kt-error-url");
|
||||
if (errorURL) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", errorURL);
|
||||
@@ -555,22 +555,22 @@ var HTMx = HTMx || (function () {
|
||||
function triggerEvent(elt, eventName, details) {
|
||||
details["elt"] = elt;
|
||||
var event = makeEvent(eventName, details);
|
||||
if (HTMx.logger) {
|
||||
HTMx.logger(elt, eventName, details);
|
||||
if (kutty.logger) {
|
||||
kutty.logger(elt, eventName, details);
|
||||
if (eventName.indexOf("Error") > 0) {
|
||||
sendError(elt, eventName, details);
|
||||
}
|
||||
}
|
||||
var eventResult = elt.dispatchEvent(event);
|
||||
var allResult = elt.dispatchEvent(makeEvent("all.hx", {elt:elt, originalDetails:details, originalEvent: event}));
|
||||
var allResult = elt.dispatchEvent(makeEvent("all.kutty", {elt:elt, originalDetails:details, originalEvent: event}));
|
||||
return eventResult && allResult;
|
||||
}
|
||||
|
||||
function addHTMxEventListener(arg1, arg2, arg3) {
|
||||
function addKuttyEventListener(arg1, arg2, arg3) {
|
||||
var target, event, listener;
|
||||
if (isFunction(arg1)) {
|
||||
target = getDocument().body;
|
||||
event = "all.hx";
|
||||
event = "all.kutty";
|
||||
listener = arg1;
|
||||
} else if (isFunction(arg2)) {
|
||||
target = getDocument().body;
|
||||
@@ -588,7 +588,7 @@ var HTMx = HTMx || (function () {
|
||||
// History Support
|
||||
//====================================================================
|
||||
function getHistoryElement() {
|
||||
var historyElt = getDocument().querySelector('.hx-history-element');
|
||||
var historyElt = getDocument().querySelector('.kt-history-element');
|
||||
return historyElt || getDocument().body;
|
||||
}
|
||||
|
||||
@@ -607,21 +607,21 @@ var HTMx = HTMx || (function () {
|
||||
}
|
||||
|
||||
function bumpHistoryAccessDate(pathAndSearch) {
|
||||
var historyTimestamps = JSON.parse(localStorage.getItem("hx-history-timestamps")) || {};
|
||||
var historyTimestamps = JSON.parse(localStorage.getItem("kt-history-timestamps")) || {};
|
||||
historyTimestamps[pathAndSearch] = Date.now();
|
||||
var paths = Object.keys(historyTimestamps);
|
||||
if (paths.length > 20) {
|
||||
purgeOldestPaths(paths, historyTimestamps);
|
||||
}
|
||||
localStorage.setItem("hx-history-timestamps", JSON.stringify(historyTimestamps));
|
||||
localStorage.setItem("kt-history-timestamps", JSON.stringify(historyTimestamps));
|
||||
}
|
||||
|
||||
function saveHistory() {
|
||||
var elt = getHistoryElement();
|
||||
var pathAndSearch = location.pathname+location.search;
|
||||
triggerEvent(getDocument().body, "historyUpdate.hx", {path:pathAndSearch, historyElement:elt});
|
||||
triggerEvent(getDocument().body, "historyUpdate.kutty", {path:pathAndSearch, historyElement:elt});
|
||||
history.replaceState({}, getDocument().title, window.location.href);
|
||||
localStorage.setItem('hx-history:' + pathAndSearch, elt.innerHTML);
|
||||
localStorage.setItem('kt-history:' + pathAndSearch, elt.innerHTML);
|
||||
bumpHistoryAccessDate(pathAndSearch);
|
||||
}
|
||||
|
||||
@@ -636,14 +636,14 @@ var HTMx = HTMx || (function () {
|
||||
}
|
||||
|
||||
function loadHistoryFromServer(pathAndSearch) {
|
||||
triggerEvent(getDocument().body, "historyCacheMiss.hx", {path: pathAndSearch});
|
||||
triggerEvent(getDocument().body, "historyCacheMiss.kutty", {path: pathAndSearch});
|
||||
var request = new XMLHttpRequest();
|
||||
request.open('GET', pathAndSearch, true);
|
||||
request.onload = function () {
|
||||
triggerEvent(getDocument().body, "historyCacheMissLoad.hx", {path: pathAndSearch});
|
||||
triggerEvent(getDocument().body, "historyCacheMissLoad.kutty", {path: pathAndSearch});
|
||||
if (this.status >= 200 && this.status < 400) {
|
||||
var fragment = makeFragment(this.response);
|
||||
fragment = fragment.querySelector('.hx-history-element') || fragment;
|
||||
fragment = fragment.querySelector('.kt-history-element') || fragment;
|
||||
settleImmediately(swapInnerHTML(getHistoryElement(), fragment));
|
||||
}
|
||||
};
|
||||
@@ -651,8 +651,8 @@ var HTMx = HTMx || (function () {
|
||||
|
||||
function restoreHistory() {
|
||||
var pathAndSearch = location.pathname+location.search;
|
||||
triggerEvent(getDocument().body, "historyRestore.hx", {path:pathAndSearch});
|
||||
var content = localStorage.getItem('hx-history:' + pathAndSearch);
|
||||
triggerEvent(getDocument().body, "historyRestore.kutty", {path:pathAndSearch});
|
||||
var content = localStorage.getItem('kt-history:' + pathAndSearch);
|
||||
if (content) {
|
||||
bumpHistoryAccessDate(pathAndSearch);
|
||||
settleImmediately(swapInnerHTML(getHistoryElement(), makeFragment(content)));
|
||||
@@ -662,7 +662,7 @@ var HTMx = HTMx || (function () {
|
||||
}
|
||||
|
||||
function shouldPush(elt) {
|
||||
return getClosestAttributeValue(elt, "hx-push-url") === "true" ||
|
||||
return getClosestAttributeValue(elt, "kt-push-url") === "true" ||
|
||||
(elt.tagName === "A" && getInternalData(elt).boosted);
|
||||
}
|
||||
|
||||
@@ -675,14 +675,14 @@ var HTMx = HTMx || (function () {
|
||||
}
|
||||
|
||||
function mutateRequestIndicatorClasses(elt, action) {
|
||||
var indicator = getClosestAttributeValue(elt, 'hx-indicator');
|
||||
var indicator = getClosestAttributeValue(elt, 'kt-indicator');
|
||||
if (indicator) {
|
||||
var indicators = getDocument().querySelectorAll(indicator);
|
||||
} else {
|
||||
indicators = [elt];
|
||||
}
|
||||
forEach(indicators, function(ic) {
|
||||
ic.classList[action].call(ic.classList, "hx-show-indicator");
|
||||
ic.classList[action].call(ic.classList, "kutty-show-indicator");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -735,7 +735,7 @@ var HTMx = HTMx || (function () {
|
||||
processInputValue(processed, values, elt);
|
||||
|
||||
// include any explicit includes
|
||||
var includes = getAttributeValue(elt, "hx-include");
|
||||
var includes = getAttributeValue(elt, "kt-include");
|
||||
if (includes) {
|
||||
var nodes = getDocument().querySelectorAll(includes);
|
||||
forEach(nodes, function(node) {
|
||||
@@ -778,7 +778,7 @@ var HTMx = HTMx || (function () {
|
||||
//====================================================================
|
||||
|
||||
function setHeader(xhr, name, value, noPrefix) {
|
||||
xhr.setRequestHeader((noPrefix ? "" : "X-HX-") + name, value || "");
|
||||
xhr.setRequestHeader((noPrefix ? "" : "X-KT-") + name, value || "");
|
||||
}
|
||||
|
||||
function setRequestHeaders(xhr, elt, target, prompt, eventTarget) {
|
||||
@@ -813,13 +813,13 @@ var HTMx = HTMx || (function () {
|
||||
eltData.requestInFlight = false
|
||||
}
|
||||
var target = getTarget(elt);
|
||||
var promptQuestion = getClosestAttributeValue(elt, "hx-prompt");
|
||||
var promptQuestion = getClosestAttributeValue(elt, "kt-prompt");
|
||||
if (promptQuestion) {
|
||||
var prompt = prompt(promptQuestion);
|
||||
if(!triggerEvent(elt, 'prompt.hx', {prompt: prompt, target:target})) return endRequestLock();
|
||||
if(!triggerEvent(elt, 'prompt.kutty', {prompt: prompt, target:target})) return endRequestLock();
|
||||
}
|
||||
|
||||
var confirmQuestion = getClosestAttributeValue(elt, "hx-confirm");
|
||||
var confirmQuestion = getClosestAttributeValue(elt, "kt-confirm");
|
||||
if (confirmQuestion) {
|
||||
if(!confirm(confirmQuestion)) return endRequestLock();
|
||||
}
|
||||
@@ -827,7 +827,7 @@ var HTMx = HTMx || (function () {
|
||||
var xhr = new XMLHttpRequest();
|
||||
|
||||
var inputValues = getInputValues(elt);
|
||||
if(!triggerEvent(elt, 'values.hx', {values: inputValues, target:target})) return endRequestLock();
|
||||
if(!triggerEvent(elt, 'values.kutty', {values: inputValues, target:target})) return endRequestLock();
|
||||
|
||||
// request type
|
||||
var requestURL;
|
||||
@@ -852,10 +852,10 @@ var HTMx = HTMx || (function () {
|
||||
|
||||
xhr.onload = function () {
|
||||
try {
|
||||
if (!triggerEvent(elt, 'beforeOnLoad.hx', {xhr: xhr, target: target})) return;
|
||||
if (!triggerEvent(elt, 'beforeOnLoad.kutty', {xhr: xhr, target: target})) return;
|
||||
|
||||
handleTrigger(elt, this.getResponseHeader("X-HX-Trigger"));
|
||||
var pushedUrl = this.getResponseHeader("X-HX-Push")
|
||||
handleTrigger(elt, this.getResponseHeader("X-KT-Trigger"));
|
||||
var pushedUrl = this.getResponseHeader("X-KT-Push")
|
||||
|
||||
var shouldSaveHistory = shouldPush(elt) || pushedUrl;
|
||||
|
||||
@@ -864,47 +864,47 @@ var HTMx = HTMx || (function () {
|
||||
if (this.status !== 204) {
|
||||
// Success!
|
||||
var resp = this.response;
|
||||
if (!triggerEvent(elt, 'beforeSwap.hx', {xhr: xhr, target: target})) return;
|
||||
if (!triggerEvent(elt, 'beforeSwap.kutty', {xhr: xhr, target: target})) return;
|
||||
|
||||
// Save current page
|
||||
if (shouldSaveHistory) {
|
||||
saveHistory();
|
||||
}
|
||||
|
||||
target.classList.add("hx-swapping");
|
||||
target.classList.add("kutty-swapping");
|
||||
var doSwap = function () {
|
||||
try {
|
||||
var settleTasks = swapResponse(target, elt, resp);
|
||||
target.classList.remove("hx-swapping");
|
||||
target.classList.add("hx-settling");
|
||||
triggerEvent(elt, 'afterSwap.hx', {xhr: xhr, target: target});
|
||||
target.classList.remove("kutty-swapping");
|
||||
target.classList.add("kutty-settling");
|
||||
triggerEvent(elt, 'afterSwap.kutty', {xhr: xhr, target: target});
|
||||
|
||||
var doSettle = function(){
|
||||
forEach(settleTasks, function (settleTask) {
|
||||
settleTask.call();
|
||||
});
|
||||
target.classList.remove("hx-settling");
|
||||
target.classList.remove("kutty-settling");
|
||||
// push URL and save new page
|
||||
if (shouldSaveHistory) {
|
||||
pushUrlIntoHistory(pushedUrl || requestURL );
|
||||
saveHistory();
|
||||
}
|
||||
triggerEvent(elt, 'afterSettle.hx', {xhr: xhr, target: target});
|
||||
triggerEvent(elt, 'afterSettle.kutty', {xhr: xhr, target: target});
|
||||
}
|
||||
|
||||
var settleDelayStr = getAttributeValue(elt, "hx-settle-delay") || "100ms";
|
||||
var settleDelayStr = getAttributeValue(elt, "kt-settle-delay") || "100ms";
|
||||
if (settleDelayStr) {
|
||||
setTimeout(doSettle, parseInterval(settleDelayStr))
|
||||
} else {
|
||||
doSettle();
|
||||
}
|
||||
} catch (e) {
|
||||
triggerEvent(elt, 'swapError.hx', {xhr: xhr, response: xhr.response, status: xhr.status, target: target});
|
||||
triggerEvent(elt, 'swapError.kutty', {xhr: xhr, response: xhr.response, status: xhr.status, target: target});
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
var swapDelayStr = getAttributeValue(elt, "hx-swap-delay");
|
||||
var swapDelayStr = getAttributeValue(elt, "kt-swap-delay");
|
||||
if (swapDelayStr) {
|
||||
setTimeout(doSwap, parseInterval(swapDelayStr))
|
||||
} else {
|
||||
@@ -912,22 +912,22 @@ var HTMx = HTMx || (function () {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
triggerEvent(elt, 'responseError.hx', {xhr: xhr, response: xhr.response, status: xhr.status, target: target});
|
||||
triggerEvent(elt, 'responseError.kutty', {xhr: xhr, response: xhr.response, status: xhr.status, target: target});
|
||||
}
|
||||
} catch (e) {
|
||||
triggerEvent(elt, 'onLoadError.hx', {xhr: xhr, response: xhr.response, status: xhr.status, target: target});
|
||||
triggerEvent(elt, 'onLoadError.kutty', {xhr: xhr, response: xhr.response, status: xhr.status, target: target});
|
||||
throw e;
|
||||
} finally {
|
||||
removeRequestIndicatorClasses(elt);
|
||||
endRequestLock();
|
||||
triggerEvent(elt, 'afterOnLoad.hx', {xhr: xhr, response: xhr.response, status: xhr.status, target: target});
|
||||
triggerEvent(elt, 'afterOnLoad.kutty', {xhr: xhr, response: xhr.response, status: xhr.status, target: target});
|
||||
}
|
||||
}
|
||||
xhr.onerror = function () {
|
||||
removeRequestIndicatorClasses(elt);triggerEvent(elt, 'loadError.hx', {xhr:xhr});
|
||||
removeRequestIndicatorClasses(elt);triggerEvent(elt, 'loadError.kutty', {xhr:xhr});
|
||||
endRequestLock();
|
||||
}
|
||||
if(!triggerEvent(elt, 'beforeRequest.hx', {xhr:xhr, values: inputValues, target:target})) return endRequestLock();
|
||||
if(!triggerEvent(elt, 'beforeRequest.kutty', {xhr:xhr, values: inputValues, target:target})) return endRequestLock();
|
||||
addRequestIndicatorClasses(elt);
|
||||
xhr.send(verb === 'get' ? null : urlEncode(inputValues));
|
||||
}
|
||||
@@ -959,8 +959,8 @@ var HTMx = HTMx || (function () {
|
||||
// Public API
|
||||
return {
|
||||
processElement: processNode,
|
||||
on: addHTMxEventListener,
|
||||
version: "0.0.2",
|
||||
on: addKuttyEventListener,
|
||||
version: "0.0.1",
|
||||
_:internalEval
|
||||
}
|
||||
}
|
||||
64
test/ajax.js
64
test/ajax.js
@@ -1,4 +1,4 @@
|
||||
describe("HTMx AJAX Tests", function(){
|
||||
describe("kutty AJAX Tests", function(){
|
||||
beforeEach(function() {
|
||||
this.server = makeServer();
|
||||
clearWorkArea();
|
||||
@@ -13,7 +13,7 @@ describe("HTMx AJAX Tests", function(){
|
||||
{
|
||||
this.server.respondWith("GET", "/test", "Clicked!");
|
||||
|
||||
var btn = make('<button hx-get="/test">Click Me!</button>')
|
||||
var btn = make('<button kt-get="/test">Click Me!</button>')
|
||||
btn.click();
|
||||
this.server.respond();
|
||||
btn.innerHTML.should.equal("Clicked!");
|
||||
@@ -21,13 +21,13 @@ describe("HTMx AJAX Tests", function(){
|
||||
|
||||
it('processes inner content properly', function()
|
||||
{
|
||||
this.server.respondWith("GET", "/test", '<a hx-get="/test2">Click Me</a>');
|
||||
this.server.respondWith("GET", "/test", '<a kt-get="/test2">Click Me</a>');
|
||||
this.server.respondWith("GET", "/test2", "Clicked!");
|
||||
|
||||
var div = make('<div hx-get="/test"></div>')
|
||||
var div = make('<div kt-get="/test"></div>')
|
||||
div.click();
|
||||
this.server.respond();
|
||||
div.innerHTML.should.equal('<a hx-get="/test2">Click Me</a>');
|
||||
div.innerHTML.should.equal('<a kt-get="/test2">Click Me</a>');
|
||||
var a = div.querySelector('a');
|
||||
a.click();
|
||||
this.server.respond();
|
||||
@@ -36,10 +36,10 @@ describe("HTMx AJAX Tests", function(){
|
||||
|
||||
it('handles swap outerHTML properly', function()
|
||||
{
|
||||
this.server.respondWith("GET", "/test", '<a id="a1" hx-get="/test2">Click Me</a>');
|
||||
this.server.respondWith("GET", "/test", '<a id="a1" kt-get="/test2">Click Me</a>');
|
||||
this.server.respondWith("GET", "/test2", "Clicked!");
|
||||
|
||||
var div = make('<div id="d1" hx-get="/test" hx-swap="outerHTML"></div>')
|
||||
var div = make('<div id="d1" kt-get="/test" kt-swap="outerHTML"></div>')
|
||||
div.click();
|
||||
should.equal(byId("d1"), div);
|
||||
this.server.respond();
|
||||
@@ -54,11 +54,11 @@ describe("HTMx AJAX Tests", function(){
|
||||
var i = 0;
|
||||
this.server.respondWith("GET", "/test", function(xhr){
|
||||
i++;
|
||||
xhr.respond(200, {}, '<a id="a' + i + '" hx-get="/test2" hx-swap="innerHTML">' + i + '</a>');
|
||||
xhr.respond(200, {}, '<a id="a' + i + '" kt-get="/test2" kt-swap="innerHTML">' + i + '</a>');
|
||||
});
|
||||
this.server.respondWith("GET", "/test2", "*");
|
||||
|
||||
var div = make('<div hx-get="/test" hx-swap="prependBefore">*</div>')
|
||||
var div = make('<div kt-get="/test" kt-swap="prependBefore">*</div>')
|
||||
var parent = div.parentElement;
|
||||
div.click();
|
||||
this.server.respond();
|
||||
@@ -84,11 +84,11 @@ describe("HTMx AJAX Tests", function(){
|
||||
var i = 0;
|
||||
this.server.respondWith("GET", "/test", function(xhr){
|
||||
i++;
|
||||
xhr.respond(200, {}, '<a id="a' + i + '" hx-get="/test2" hx-swap="innerHTML">' + i + '</a>');
|
||||
xhr.respond(200, {}, '<a id="a' + i + '" kt-get="/test2" kt-swap="innerHTML">' + i + '</a>');
|
||||
});
|
||||
this.server.respondWith("GET", "/test2", "*");
|
||||
|
||||
var div = make('<div hx-get="/test" hx-swap="prepend">*</div>')
|
||||
var div = make('<div kt-get="/test" kt-swap="prepend">*</div>')
|
||||
div.click();
|
||||
this.server.respond();
|
||||
div.innerText.should.equal("1*");
|
||||
@@ -111,11 +111,11 @@ describe("HTMx AJAX Tests", function(){
|
||||
var i = 0;
|
||||
this.server.respondWith("GET", "/test", function(xhr){
|
||||
i++;
|
||||
xhr.respond(200, {}, '<a id="a' + i + '" hx-get="/test2" hx-swap="innerHTML">' + i + '</a>');
|
||||
xhr.respond(200, {}, '<a id="a' + i + '" kt-get="/test2" kt-swap="innerHTML">' + i + '</a>');
|
||||
});
|
||||
this.server.respondWith("GET", "/test2", "*");
|
||||
|
||||
var div = make('<div hx-get="/test" hx-swap="prepend"></div>')
|
||||
var div = make('<div kt-get="/test" kt-swap="prepend"></div>')
|
||||
div.click();
|
||||
this.server.respond();
|
||||
div.innerText.should.equal("1");
|
||||
@@ -138,11 +138,11 @@ describe("HTMx AJAX Tests", function(){
|
||||
var i = 0;
|
||||
this.server.respondWith("GET", "/test", function(xhr){
|
||||
i++;
|
||||
xhr.respond(200, {}, '<a id="a' + i + '" hx-get="/test2" hx-swap="innerHTML">' + i + '</a>');
|
||||
xhr.respond(200, {}, '<a id="a' + i + '" kt-get="/test2" kt-swap="innerHTML">' + i + '</a>');
|
||||
});
|
||||
this.server.respondWith("GET", "/test2", "*");
|
||||
|
||||
var div = make('<div hx-get="/test" hx-swap="appendAfter">*</div>')
|
||||
var div = make('<div kt-get="/test" kt-swap="appendAfter">*</div>')
|
||||
var parent = div.parentElement;
|
||||
div.click();
|
||||
this.server.respond();
|
||||
@@ -168,11 +168,11 @@ describe("HTMx AJAX Tests", function(){
|
||||
var i = 0;
|
||||
this.server.respondWith("GET", "/test", function(xhr){
|
||||
i++;
|
||||
xhr.respond(200, {}, '<a id="a' + i + '" hx-get="/test2" hx-swap="innerHTML">' + i + '</a>');
|
||||
xhr.respond(200, {}, '<a id="a' + i + '" kt-get="/test2" kt-swap="innerHTML">' + i + '</a>');
|
||||
});
|
||||
this.server.respondWith("GET", "/test2", "*");
|
||||
|
||||
var div = make('<div hx-get="/test" hx-swap="append">*</div>')
|
||||
var div = make('<div kt-get="/test" kt-swap="append">*</div>')
|
||||
div.click();
|
||||
this.server.respond();
|
||||
div.innerText.should.equal("*1");
|
||||
@@ -195,11 +195,11 @@ describe("HTMx AJAX Tests", function(){
|
||||
var i = 0;
|
||||
this.server.respondWith("GET", "/test", function(xhr){
|
||||
i++;
|
||||
xhr.respond(200, {}, '<a id="a' + i + '" hx-get="/test2" hx-swap="innerHTML">' + i + '</a>');
|
||||
xhr.respond(200, {}, '<a id="a' + i + '" kt-get="/test2" kt-swap="innerHTML">' + i + '</a>');
|
||||
});
|
||||
this.server.respondWith("GET", "/test2", "*");
|
||||
|
||||
var div = make('<div hx-get="/test" hx-swap="append"></div>')
|
||||
var div = make('<div kt-get="/test" kt-swap="append"></div>')
|
||||
div.click();
|
||||
this.server.respond();
|
||||
div.innerText.should.equal("1");
|
||||
@@ -217,11 +217,11 @@ describe("HTMx AJAX Tests", function(){
|
||||
div.innerText.should.equal("**");
|
||||
});
|
||||
|
||||
it('handles hx-target properly', function()
|
||||
it('handles kt-target properly', function()
|
||||
{
|
||||
this.server.respondWith("GET", "/test", "Clicked!");
|
||||
|
||||
var btn = make('<button hx-get="/test" hx-target="#s1">Click Me!</button>');
|
||||
var btn = make('<button kt-get="/test" kt-target="#s1">Click Me!</button>');
|
||||
var target = make('<span id="s1">Initial</span>');
|
||||
btn.click();
|
||||
target.innerHTML.should.equal("Initial");
|
||||
@@ -233,28 +233,28 @@ describe("HTMx AJAX Tests", function(){
|
||||
{
|
||||
this.server.respondWith("GET", "/test", [204, {}, "No Content!"]);
|
||||
|
||||
var btn = make('<button hx-get="/test">Click Me!</button>');
|
||||
var btn = make('<button kt-get="/test">Click Me!</button>');
|
||||
btn.click();
|
||||
btn.innerHTML.should.equal("Click Me!");
|
||||
this.server.respond();
|
||||
btn.innerHTML.should.equal("Click Me!");
|
||||
});
|
||||
|
||||
it('handles hx-trigger with non-default value', function()
|
||||
it('handles kt-trigger with non-default value', function()
|
||||
{
|
||||
this.server.respondWith("GET", "/test", "Focused!");
|
||||
|
||||
var btn = make('<button hx-get="/test" hx-trigger="focus">Focus Me!</button>');
|
||||
var btn = make('<button kt-get="/test" kt-trigger="focus">Focus Me!</button>');
|
||||
btn.focus();
|
||||
btn.innerHTML.should.equal("Focus Me!");
|
||||
this.server.respond();
|
||||
btn.innerHTML.should.equal("Focused!");
|
||||
});
|
||||
|
||||
it('handles hx-trigger with load event', function()
|
||||
it('handles kt-trigger with load event', function()
|
||||
{
|
||||
this.server.respondWith("GET", "/test", "Loaded!");
|
||||
var div = make('<div hx-get="/test" hx-trigger="load">Load Me!</div>');
|
||||
var div = make('<div kt-get="/test" kt-trigger="load">Load Me!</div>');
|
||||
div.innerHTML.should.equal("Load Me!");
|
||||
this.server.respond();
|
||||
div.innerHTML.should.equal("Loaded!");
|
||||
@@ -266,7 +266,7 @@ describe("HTMx AJAX Tests", function(){
|
||||
xhr.overriddenMimeType.should.equal("text/html");
|
||||
done();
|
||||
});
|
||||
var div = make('<div hx-get="/test">Click Me!</div>');
|
||||
var div = make('<div kt-get="/test">Click Me!</div>');
|
||||
div.click();
|
||||
this.server.respond();
|
||||
});
|
||||
@@ -278,28 +278,28 @@ describe("HTMx AJAX Tests", function(){
|
||||
xhr.respond(200, {}, "click " + i);
|
||||
i++
|
||||
});
|
||||
var div = make('<div hx-get="/test"></div>');
|
||||
var div = make('<div kt-get="/test"></div>');
|
||||
div.click();
|
||||
div.click();
|
||||
this.server.respond();
|
||||
div.innerHTML.should.equal("click 1");
|
||||
});
|
||||
|
||||
it('properly handles hx-select for basic situation', function()
|
||||
it('properly handles kt-select for basic situation', function()
|
||||
{
|
||||
var i = 1;
|
||||
this.server.respondWith("GET", "/test", "<div id='d1'>foo</div><div id='d2'>bar</div>");
|
||||
var div = make('<div hx-get="/test" hx-select="#d1"></div>');
|
||||
var div = make('<div kt-get="/test" kt-select="#d1"></div>');
|
||||
div.click();
|
||||
this.server.respond();
|
||||
div.innerHTML.should.equal("<div id=\"d1\">foo</div>");
|
||||
});
|
||||
|
||||
it('properly handles hx-select for full html document situation', function()
|
||||
it('properly handles kt-select for full html document situation', function()
|
||||
{
|
||||
var i = 1;
|
||||
this.server.respondWith("GET", "/test", "<html><body><div id='d1'>foo</div><div id='d2'>bar</div></body></html>");
|
||||
var div = make('<div hx-get="/test" hx-select="#d1"></div>');
|
||||
var div = make('<div kt-get="/test" kt-select="#d1"></div>');
|
||||
div.click();
|
||||
this.server.respond();
|
||||
div.innerHTML.should.equal("<div id=\"d1\">foo</div>");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
describe("HTMx Boost Tests", function() {
|
||||
describe("kutty Boost Tests", function() {
|
||||
|
||||
beforeEach(function () {
|
||||
this.server = makeServer();
|
||||
@@ -11,7 +11,7 @@ describe("HTMx Boost Tests", function() {
|
||||
|
||||
it('handles basic anchor properly', function () {
|
||||
this.server.respondWith("GET", "/test", "Boosted");
|
||||
var div = make('<div hx-target="this" hx-boost="true"><a id="a1" href="/test">Foo</a></div>');
|
||||
var div = make('<div kt-target="this" kt-boost="true"><a id="a1" href="/test">Foo</a></div>');
|
||||
var a = byId('a1');
|
||||
a.click();
|
||||
this.server.respond();
|
||||
@@ -23,7 +23,7 @@ describe("HTMx Boost Tests", function() {
|
||||
it('handles basic form post properly', function () {
|
||||
this.server.respondWith("POST", "/test", "Boosted");
|
||||
this.server.respondWith("POST", "/test", "Boosted");
|
||||
var div = make('<div hx-target="this" hx-boost="true"><form id="f1" action="/test" method="post"><button id="b1">Submit</button></form></div>');
|
||||
var div = make('<div kt-target="this" kt-boost="true"><form id="f1" action="/test" method="post"><button id="b1">Submit</button></form></div>');
|
||||
var btn = byId('b1');
|
||||
btn.click();
|
||||
this.server.respond();
|
||||
@@ -33,7 +33,7 @@ describe("HTMx Boost Tests", function() {
|
||||
|
||||
it('handles basic form get properly', function () {
|
||||
this.server.respondWith("GET", "/test", "Boosted");
|
||||
var div = make('<div hx-target="this" hx-boost="true"><form id="f1" action="/test" method="get"><button id="b1">Submit</button></form></div>');
|
||||
var div = make('<div kt-target="this" kt-boost="true"><form id="f1" action="/test" method="get"><button id="b1">Submit</button></form></div>');
|
||||
var btn = byId('b1');
|
||||
btn.click();
|
||||
this.server.respond();
|
||||
@@ -43,7 +43,7 @@ describe("HTMx Boost Tests", function() {
|
||||
|
||||
it('handles basic form with no explicit method property', function () {
|
||||
this.server.respondWith("GET", "/test", "Boosted");
|
||||
var div = make('<div hx-target="this" hx-boost="true"><form id="f1" action="/test"><button id="b1">Submit</button></form></div>');
|
||||
var div = make('<div kt-target="this" kt-boost="true"><form id="f1" action="/test"><button id="b1">Submit</button></form></div>');
|
||||
var btn = byId('b1');
|
||||
btn.click();
|
||||
this.server.respond();
|
||||
|
||||
33
test/browser-only.html
Normal file
33
test/browser-only.html
Normal file
@@ -0,0 +1,33 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Mocha Tests</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="stylesheet" href="../node_modules/mocha/mocha.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="mocha"></div>
|
||||
<script src="../node_modules/chai/chai.js"></script>
|
||||
<script src="../node_modules/mocha/mocha.js"></script>
|
||||
<script src="../node_modules/sinon/pkg/sinon.js"></script>
|
||||
<script src="../src/kutty.js"></script>
|
||||
<script class="mocha-init">
|
||||
mocha.setup('bdd');
|
||||
mocha.checkLeaks();
|
||||
should = chai.should();
|
||||
</script>
|
||||
|
||||
<script src="util.js"></script>
|
||||
<script src="history.js"></script>
|
||||
<script src="boost.js"></script>
|
||||
|
||||
|
||||
<script class="mocha-exec">
|
||||
mocha.run();
|
||||
</script>
|
||||
<em>Work Area</em>
|
||||
<hr/>
|
||||
<div id="work-area" class="kt-history-element">
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,4 +1,4 @@
|
||||
describe("HTMx class modification attributes", function(){
|
||||
describe("kutty class modification attributes", function(){
|
||||
beforeEach(function() {
|
||||
this.server = makeServer();
|
||||
clearWorkArea();
|
||||
@@ -10,7 +10,7 @@ describe("HTMx class modification attributes", function(){
|
||||
|
||||
it('adds classes properly', function(done)
|
||||
{
|
||||
var div = make('<div hx-add-class="c1">Click Me!</div>')
|
||||
var div = make('<div kt-add-class="c1">Click Me!</div>')
|
||||
should.equal(div.classList.length, 0);
|
||||
setTimeout(function(){
|
||||
should.equal(div.classList.contains("c1"), true);
|
||||
@@ -20,7 +20,7 @@ describe("HTMx class modification attributes", function(){
|
||||
|
||||
it('removes classes properly', function(done)
|
||||
{
|
||||
var div = make('<div class="foo bar" hx-remove-class="bar">Click Me!</div>')
|
||||
var div = make('<div class="foo bar" kt-remove-class="bar">Click Me!</div>')
|
||||
should.equal(div.classList.contains("foo"), true);
|
||||
should.equal(div.classList.contains("bar"), true);
|
||||
setTimeout(function(){
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
describe("HTMx Events", function() {
|
||||
describe("kutty Events", function() {
|
||||
beforeEach(function () {
|
||||
this.server = makeServer();
|
||||
clearWorkArea();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
describe("HTMx AJAX Headers Tests", function() {
|
||||
describe("kutty AJAX Headers Tests", function() {
|
||||
beforeEach(function () {
|
||||
this.server = makeServer();
|
||||
clearWorkArea();
|
||||
@@ -8,50 +8,50 @@ describe("HTMx AJAX Headers Tests", function() {
|
||||
clearWorkArea();
|
||||
});
|
||||
|
||||
it("should include the X-HX-Request header", function(){
|
||||
it("should include the X-KT-Request header", function(){
|
||||
this.server.respondWith("GET", "/test", function(xhr){
|
||||
xhr.requestHeaders['X-HX-Request'].should.be.equal('true');
|
||||
xhr.requestHeaders['X-KT-Request'].should.be.equal('true');
|
||||
xhr.respond(200, {}, "");
|
||||
});
|
||||
var div = make('<div hx-get="/test"></div>');
|
||||
var div = make('<div kt-get="/test"></div>');
|
||||
div.click();
|
||||
this.server.respond();
|
||||
})
|
||||
|
||||
it("should include the X-HX-Trigger-Id header", function(){
|
||||
it("should include the X-KT-Trigger-Id header", function(){
|
||||
this.server.respondWith("GET", "/test", function(xhr){
|
||||
xhr.requestHeaders['X-HX-Trigger-Id'].should.equal('d1');
|
||||
xhr.requestHeaders['X-KT-Trigger-Id'].should.equal('d1');
|
||||
xhr.respond(200, {}, "");
|
||||
});
|
||||
var div = make('<div id="d1" hx-get="/test"></div>');
|
||||
var div = make('<div id="d1" kt-get="/test"></div>');
|
||||
div.click();
|
||||
this.server.respond();
|
||||
})
|
||||
|
||||
it("should include the X-HX-Trigger-Name header", function(){
|
||||
it("should include the X-KT-Trigger-Name header", function(){
|
||||
this.server.respondWith("GET", "/test", function(xhr){
|
||||
xhr.requestHeaders['X-HX-Trigger-Name'].should.equal('n1');
|
||||
xhr.requestHeaders['X-KT-Trigger-Name'].should.equal('n1');
|
||||
xhr.respond(200, {}, "");
|
||||
});
|
||||
var div = make('<button name="n1" hx-get="/test"></button>');
|
||||
var div = make('<button name="n1" kt-get="/test"></button>');
|
||||
div.click();
|
||||
this.server.respond();
|
||||
})
|
||||
|
||||
it("should include the X-HX-Target-Id header", function(){
|
||||
it("should include the X-KT-Target-Id header", function(){
|
||||
this.server.respondWith("GET", "/test", function(xhr){
|
||||
xhr.requestHeaders['X-HX-Target-Id'].should.equal('d1');
|
||||
xhr.requestHeaders['X-KT-Target-Id'].should.equal('d1');
|
||||
xhr.respond(200, {}, "");
|
||||
});
|
||||
var div = make('<div hx-target="#d1" hx-get="/test"></div><div id="d1" ></div>');
|
||||
var div = make('<div kt-target="#d1" kt-get="/test"></div><div id="d1" ></div>');
|
||||
div.click();
|
||||
this.server.respond();
|
||||
})
|
||||
|
||||
it("should handle simple string X-HX-Trigger response header properly", function(){
|
||||
this.server.respondWith("GET", "/test", [200, {"X-HX-Trigger" : "foo"}, ""]);
|
||||
it("should handle simple string X-KT-Trigger response header properly", function(){
|
||||
this.server.respondWith("GET", "/test", [200, {"X-KT-Trigger" : "foo"}, ""]);
|
||||
|
||||
var div = make('<div hx-get="/test"></div>');
|
||||
var div = make('<div kt-get="/test"></div>');
|
||||
var invokedEvent = false;
|
||||
div.addEventListener("foo", function (evt) {
|
||||
invokedEvent = true;
|
||||
@@ -61,10 +61,10 @@ describe("HTMx AJAX Headers Tests", function() {
|
||||
invokedEvent.should.equal(true);
|
||||
})
|
||||
|
||||
it("should handle basic JSON X-HX-Trigger response header properly", function(){
|
||||
this.server.respondWith("GET", "/test", [200, {"X-HX-Trigger" : "{\"foo\":null}"}, ""]);
|
||||
it("should handle basic JSON X-KT-Trigger response header properly", function(){
|
||||
this.server.respondWith("GET", "/test", [200, {"X-KT-Trigger" : "{\"foo\":null}"}, ""]);
|
||||
|
||||
var div = make('<div hx-get="/test"></div>');
|
||||
var div = make('<div kt-get="/test"></div>');
|
||||
var invokedEvent = false;
|
||||
div.addEventListener("foo", function (evt) {
|
||||
invokedEvent = true;
|
||||
@@ -76,10 +76,10 @@ describe("HTMx AJAX Headers Tests", function() {
|
||||
invokedEvent.should.equal(true);
|
||||
})
|
||||
|
||||
it("should handle JSON with array arg X-HX-Trigger response header properly", function(){
|
||||
this.server.respondWith("GET", "/test", [200, {"X-HX-Trigger" : "{\"foo\":[1, 2, 3]}"}, ""]);
|
||||
it("should handle JSON with array arg X-KT-Trigger response header properly", function(){
|
||||
this.server.respondWith("GET", "/test", [200, {"X-KT-Trigger" : "{\"foo\":[1, 2, 3]}"}, ""]);
|
||||
|
||||
var div = make('<div hx-get="/test"></div>');
|
||||
var div = make('<div kt-get="/test"></div>');
|
||||
var invokedEvent = false;
|
||||
div.addEventListener("foo", function (evt) {
|
||||
invokedEvent = true;
|
||||
@@ -91,10 +91,10 @@ describe("HTMx AJAX Headers Tests", function() {
|
||||
invokedEvent.should.equal(true);
|
||||
})
|
||||
|
||||
it("should handle JSON with array arg X-HX-Trigger response header properly", function(){
|
||||
this.server.respondWith("GET", "/test", [200, {"X-HX-Trigger" : "{\"foo\":{\"a\":1, \"b\":2}}"}, ""]);
|
||||
it("should handle JSON with array arg X-KT-Trigger response header properly", function(){
|
||||
this.server.respondWith("GET", "/test", [200, {"X-KT-Trigger" : "{\"foo\":{\"a\":1, \"b\":2}}"}, ""]);
|
||||
|
||||
var div = make('<div hx-get="/test"></div>');
|
||||
var div = make('<div kt-get="/test"></div>');
|
||||
var invokedEvent = false;
|
||||
div.addEventListener("foo", function (evt) {
|
||||
invokedEvent = true;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
describe("HTMx History Tests", function() {
|
||||
describe("kutty History Tests", function() {
|
||||
|
||||
beforeEach(function () {
|
||||
this.server = makeServer();
|
||||
@@ -13,7 +13,7 @@ describe("HTMx History Tests", function() {
|
||||
this.server.respondWith("GET", "/test", "second");
|
||||
|
||||
getWorkArea().innerHTML.should.be.equal("");
|
||||
var div = make('<div hx-push-url="true" hx-get="/test">first</div>');
|
||||
var div = make('<div kt-push-url="true" kt-get="/test">first</div>');
|
||||
div.click();
|
||||
this.server.respond();
|
||||
getWorkArea().textContent.should.equal("second")
|
||||
@@ -32,7 +32,7 @@ describe("HTMx History Tests", function() {
|
||||
});
|
||||
|
||||
getWorkArea().innerHTML.should.equal("");
|
||||
var div = make('<div hx-push-url="true" hx-get="/test" class="">0</div>');
|
||||
var div = make('<div kt-push-url="true" kt-get="/test" class="">0</div>');
|
||||
div.click();
|
||||
this.server.respond();
|
||||
getWorkArea().textContent.should.equal("1")
|
||||
@@ -56,7 +56,7 @@ describe("HTMx History Tests", function() {
|
||||
this.server.respondWith("GET", "/test", "second");
|
||||
|
||||
getWorkArea().innerHTML.should.equal("");
|
||||
var div = make('<div hx-push-url="true" hx-get="/test" class="">first</div>');
|
||||
var div = make('<div kt-push-url="true" kt-get="/test" class="">first</div>');
|
||||
div.click();
|
||||
this.server.respond();
|
||||
getWorkArea().textContent.should.equal("second")
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<script src="../node_modules/chai/chai.js"></script>
|
||||
<script src="../node_modules/mocha/mocha.js"></script>
|
||||
<script src="../node_modules/sinon/pkg/sinon.js"></script>
|
||||
<script src="../src/htmx.js"></script>
|
||||
<script src="../src/kutty.js"></script>
|
||||
<script class="mocha-init">
|
||||
mocha.setup('bdd');
|
||||
mocha.checkLeaks();
|
||||
@@ -31,12 +31,15 @@
|
||||
<!--<script src="history.js"></script>-->
|
||||
<!--<script src="boost.js"></script>-->
|
||||
|
||||
<a href="browser-only.html">Run Browser-Only Tests</a>
|
||||
|
||||
|
||||
<script class="mocha-exec">
|
||||
mocha.run();
|
||||
</script>
|
||||
<em>Work Area</em>
|
||||
<hr/>
|
||||
<div id="work-area" class="hx-history-element">
|
||||
<div id="work-area" class="kt-history-element">
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
describe("HTMx Indicator Tests", function(){
|
||||
describe("kutty Indicator Tests", function(){
|
||||
beforeEach(function() {
|
||||
this.server = sinon.fakeServer.create();
|
||||
clearWorkArea();
|
||||
@@ -11,26 +11,26 @@ describe("HTMx Indicator Tests", function(){
|
||||
it('Indicator classes are properly put on element with no explicit indicator', function()
|
||||
{
|
||||
this.server.respondWith("GET", "/test", "Clicked!");
|
||||
var btn = make('<button hx-get="/test">Click Me!</button>')
|
||||
var btn = make('<button kt-get="/test">Click Me!</button>')
|
||||
btn.click();
|
||||
btn.classList.contains("hx-show-indicator").should.equal(true);
|
||||
btn.classList.contains("kutty-show-indicator").should.equal(true);
|
||||
this.server.respond();
|
||||
btn.classList.contains("hx-show-indicator").should.equal(false);
|
||||
btn.classList.contains("kutty-show-indicator").should.equal(false);
|
||||
});
|
||||
|
||||
it('Indicator classes are properly put on element with explicit indicator', function()
|
||||
{
|
||||
this.server.respondWith("GET", "/test", "Clicked!");
|
||||
var btn = make('<button hx-get="/test" hx-indicator="#a1, #a2">Click Me!</button>')
|
||||
var btn = make('<button kt-get="/test" kt-indicator="#a1, #a2">Click Me!</button>')
|
||||
var a1 = make('<a id="a1"></a>')
|
||||
var a2 = make('<a id="a2"></a>')
|
||||
btn.click();
|
||||
btn.classList.contains("hx-show-indicator").should.equal(false);
|
||||
a1.classList.contains("hx-show-indicator").should.equal(true);
|
||||
a2.classList.contains("hx-show-indicator").should.equal(true);
|
||||
btn.classList.contains("kutty-show-indicator").should.equal(false);
|
||||
a1.classList.contains("kutty-show-indicator").should.equal(true);
|
||||
a2.classList.contains("kutty-show-indicator").should.equal(true);
|
||||
this.server.respond();
|
||||
btn.classList.contains("hx-show-indicator").should.equal(false);
|
||||
a1.classList.contains("hx-show-indicator").should.equal(false);
|
||||
a2.classList.contains("hx-show-indicator").should.equal(false);
|
||||
btn.classList.contains("kutty-show-indicator").should.equal(false);
|
||||
a1.classList.contains("kutty-show-indicator").should.equal(false);
|
||||
a2.classList.contains("kutty-show-indicator").should.equal(false);
|
||||
});
|
||||
})
|
||||
|
||||
10
test/oob.js
10
test/oob.js
@@ -1,4 +1,4 @@
|
||||
describe("HTMx Direct Swap", function () {
|
||||
describe("kutty Direct Swap", function () {
|
||||
beforeEach(function () {
|
||||
this.server = makeServer();
|
||||
clearWorkArea();
|
||||
@@ -9,8 +9,8 @@ describe("HTMx Direct Swap", function () {
|
||||
});
|
||||
|
||||
it('handles basic response properly', function () {
|
||||
this.server.respondWith("GET", "/test", "Clicked<div id='d1' hx-swap-oob='true'>Swapped</div>");
|
||||
var div = make('<div hx-get="/test">click me</div>');
|
||||
this.server.respondWith("GET", "/test", "Clicked<div id='d1' kt-swap-oob='true'>Swapped</div>");
|
||||
var div = make('<div kt-get="/test">click me</div>');
|
||||
make('<div id="d1"></div>');
|
||||
div.click();
|
||||
this.server.respond();
|
||||
@@ -19,8 +19,8 @@ describe("HTMx Direct Swap", function () {
|
||||
})
|
||||
|
||||
it('handles no id match properly', function () {
|
||||
this.server.respondWith("GET", "/test", "Clicked<div id='d1' hx-swap-oob='true'>Swapped</div>");
|
||||
var div = make('<div hx-get="/test">click me</div>');
|
||||
this.server.respondWith("GET", "/test", "Clicked<div id='d1' kt-swap-oob='true'>Swapped</div>");
|
||||
var div = make('<div kt-get="/test">click me</div>');
|
||||
div.click();
|
||||
this.server.respond();
|
||||
div.innerText.should.equal("Clicked");
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.hx-show-indicator .indicator {
|
||||
.kt-show-indicator .indicator {
|
||||
opacity: 100%;
|
||||
}
|
||||
|
||||
@@ -19,18 +19,18 @@
|
||||
</head>
|
||||
<body>
|
||||
<script src="../node_modules/sinon/pkg/sinon.js"></script>
|
||||
<script src="../src/htmx.js"></script>
|
||||
<script src="../src/kutty.js"></script>
|
||||
<script src="util.js"></script>
|
||||
<script src="scratch_server.js"></script>
|
||||
|
||||
<script>
|
||||
// this.server.respondWith("GET", "/test", '<a hx-get="/test2">Click Me</a>');
|
||||
// this.server.respondWith("GET", "/test", '<a kt-get="/test2">Click Me</a>');
|
||||
// this.server.respondWith("GET", "/test2", "Clicked!");
|
||||
//
|
||||
// make('<div hx-get="/test">dd</div>')
|
||||
// make('<div kt-get="/test">dd</div>')
|
||||
|
||||
this.server.respondWith("GET", "/test", '<div id="d1" style="color: red; margin: 100px">Foo</div>');
|
||||
make('<div hx-swap="outerHTML" hx-get="/test" hx-push-url="true" id="d1">Foo</div>');
|
||||
make('<div kt-swap="outerHTML" kt-get="/test" kt-push-url="true" id="d1">Foo</div>');
|
||||
</script>
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ Autorespond: <input id="autorespond" type="checkbox" onclick="toggleAutoRespond(
|
||||
<em>Work Area</em>
|
||||
<hr/>
|
||||
|
||||
<div id="work-area" class="hx-history-element">
|
||||
<div id="work-area" class="kt-history-element">
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
var server = makeServer();
|
||||
var autoRespond = localStorage.getItem('hx-scratch-autorespond') == "true";
|
||||
var autoRespond = localStorage.getItem('kt-scratch-autorespond') == "true";
|
||||
server.autoRespond = autoRespond;
|
||||
ready(function () {
|
||||
if (autoRespond) {
|
||||
@@ -8,10 +8,10 @@ ready(function () {
|
||||
})
|
||||
function toggleAutoRespond() {
|
||||
if (server.autoRespond) {
|
||||
localStorage.removeItem('hx-scratch-autorespond');
|
||||
localStorage.removeItem('kt-scratch-autorespond');
|
||||
server.autoRespond = false;
|
||||
} else {
|
||||
localStorage.setItem('hx-scratch-autorespond', 'true');
|
||||
localStorage.setItem('kt-scratch-autorespond', 'true');
|
||||
server.autoRespond = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Test Utilities */
|
||||
|
||||
HTMx.logger = function(elt, event, data) {
|
||||
kutty.logger = function(elt, event, data) {
|
||||
if(console) {
|
||||
console.log(event, elt, data);
|
||||
}
|
||||
@@ -17,7 +17,7 @@ function make(htmlStr) {
|
||||
var wa = getWorkArea();
|
||||
for (var i = fragment.children.length - 1; i >= 0; i--) {
|
||||
var child = fragment.children[i];
|
||||
HTMx.processElement(child);
|
||||
kutty.processElement(child);
|
||||
wa.appendChild(child);
|
||||
}
|
||||
return wa.lastChild;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
describe("HTMx Value Handling", function() {
|
||||
describe("kutty Value Handling", function() {
|
||||
beforeEach(function () {
|
||||
this.server = makeServer();
|
||||
clearWorkArea();
|
||||
@@ -10,69 +10,69 @@ describe("HTMx Value Handling", function() {
|
||||
|
||||
it('Input includes value', function () {
|
||||
var input = make('<input name="foo" value="bar"/>');
|
||||
var vals = HTMx._('getInputValues')(input);
|
||||
var vals = kutty._('getInputValues')(input);
|
||||
vals['foo'].should.equal('bar');
|
||||
})
|
||||
|
||||
it('Input includes form', function () {
|
||||
var form = make('<form><input id="i1" name="foo" value="bar"/><input id="i2" name="do" value="rey"/></form>');
|
||||
var input = byId('i1');
|
||||
var vals = HTMx._('getInputValues')(input);
|
||||
var vals = kutty._('getInputValues')(input);
|
||||
vals['foo'].should.equal('bar');
|
||||
vals['do'].should.equal('rey');
|
||||
})
|
||||
|
||||
it('Basic form works', function () {
|
||||
var form = make('<form><input id="i1" name="foo" value="bar"/><input id="i2" name="do" value="rey"/></form>');
|
||||
var vals = HTMx._('getInputValues')(form);
|
||||
var vals = kutty._('getInputValues')(form);
|
||||
vals['foo'].should.equal('bar');
|
||||
vals['do'].should.equal('rey');
|
||||
})
|
||||
|
||||
it('Double values are included as array', function () {
|
||||
var form = make('<form><input id="i1" name="foo" value="bar"/><input id="i2" name="do" value="rey"/><input id="i2" name="do" value="rey"/></form>');
|
||||
var vals = HTMx._('getInputValues')(form);
|
||||
var vals = kutty._('getInputValues')(form);
|
||||
vals['foo'].should.equal('bar');
|
||||
vals['do'].should.deep.equal(['rey', 'rey']);
|
||||
})
|
||||
|
||||
it('hx-include works with form', function () {
|
||||
it('kt-include works with form', function () {
|
||||
var form = make('<form id="f1"><input id="i1" name="foo" value="bar"/><input id="i2" name="do" value="rey"/><input id="i2" name="do" value="rey"/></form>');
|
||||
var div = make('<div hx-include="#f1"></div>');
|
||||
var vals = HTMx._('getInputValues')(div);
|
||||
var div = make('<div kt-include="#f1"></div>');
|
||||
var vals = kutty._('getInputValues')(div);
|
||||
vals['foo'].should.equal('bar');
|
||||
vals['do'].should.deep.equal(['rey', 'rey']);
|
||||
})
|
||||
|
||||
it('hx-include works with input', function () {
|
||||
it('kt-include works with input', function () {
|
||||
var form = make('<form id="f1"><input id="i1" name="foo" value="bar"/><input id="i2" name="do" value="rey"/><input id="i2" name="do" value="rey"/></form>');
|
||||
var div = make('<div hx-include="#i1"></div>');
|
||||
var vals = HTMx._('getInputValues')(div);
|
||||
var div = make('<div kt-include="#i1"></div>');
|
||||
var vals = kutty._('getInputValues')(div);
|
||||
vals['foo'].should.equal('bar');
|
||||
should.equal(vals['do'], undefined);
|
||||
})
|
||||
|
||||
it('hx-include works with two inputs', function () {
|
||||
it('kt-include works with two inputs', function () {
|
||||
var form = make('<form id="f1"><input id="i1" name="foo" value="bar"/><input id="i2" name="do" value="rey"/><input id="i2" name="do" value="rey"/></form>');
|
||||
var div = make('<div hx-include="#i1, #i2"></div>');
|
||||
var vals = HTMx._('getInputValues')(div);
|
||||
var div = make('<div kt-include="#i1, #i2"></div>');
|
||||
var vals = kutty._('getInputValues')(div);
|
||||
vals['foo'].should.equal('bar');
|
||||
vals['do'].should.deep.equal(['rey', 'rey']);
|
||||
})
|
||||
|
||||
it('hx-include works with two inputs, plus form', function () {
|
||||
it('kt-include works with two inputs, plus form', function () {
|
||||
var form = make('<form id="f1"><input id="i1" name="foo" value="bar"/><input id="i2" name="do" value="rey"/><input id="i2" name="do" value="rey"/></form>');
|
||||
var div = make('<div hx-include="#i1, #i2, #f1"></div>');
|
||||
var vals = HTMx._('getInputValues')(div);
|
||||
var div = make('<div kt-include="#i1, #i2, #f1"></div>');
|
||||
var vals = kutty._('getInputValues')(div);
|
||||
vals['foo'].should.equal('bar');
|
||||
vals['do'].should.deep.equal(['rey', 'rey']);
|
||||
})
|
||||
|
||||
it('correctly URL escapes values', function () {
|
||||
HTMx._("urlEncode")({}).should.equal("");
|
||||
HTMx._("urlEncode")({"foo": "bar"}).should.equal("foo=bar");
|
||||
HTMx._("urlEncode")({"foo": "bar", "do" : "rey"}).should.equal("foo=bar&do=rey");
|
||||
HTMx._("urlEncode")({"foo": "bar", "do" : ["rey", "blah"]}).should.equal("foo=bar&do=rey&do=blah");
|
||||
kutty._("urlEncode")({}).should.equal("");
|
||||
kutty._("urlEncode")({"foo": "bar"}).should.equal("foo=bar");
|
||||
kutty._("urlEncode")({"foo": "bar", "do" : "rey"}).should.equal("foo=bar&do=rey");
|
||||
kutty._("urlEncode")({"foo": "bar", "do" : ["rey", "blah"]}).should.equal("foo=bar&do=rey&do=blah");
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
describe("HTMx AJAX Verbs", function() {
|
||||
describe("kutty AJAX Verbs", function() {
|
||||
beforeEach(function () {
|
||||
this.server = makeServer();
|
||||
clearWorkArea();
|
||||
@@ -10,7 +10,7 @@ describe("HTMx AJAX Verbs", function() {
|
||||
|
||||
it('handles basic posts properly', function () {
|
||||
this.server.respondWith("POST", "/test", "post");
|
||||
var div = make('<div hx-post="/test">click me</div>');
|
||||
var div = make('<div kt-post="/test">click me</div>');
|
||||
div.click();
|
||||
this.server.respond();
|
||||
div.innerHTML.should.equal("post");
|
||||
@@ -18,7 +18,7 @@ describe("HTMx AJAX Verbs", function() {
|
||||
|
||||
it('handles basic put properly', function () {
|
||||
this.server.respondWith("PUT", "/test", "put");
|
||||
var div = make('<div hx-put="/test">click me</div>');
|
||||
var div = make('<div kt-put="/test">click me</div>');
|
||||
div.click();
|
||||
this.server.respond();
|
||||
div.innerHTML.should.equal("put");
|
||||
@@ -26,7 +26,7 @@ describe("HTMx AJAX Verbs", function() {
|
||||
|
||||
it('handles basic patch properly', function () {
|
||||
this.server.respondWith("PATCH", "/test", "patch");
|
||||
var div = make('<div hx-patch="/test">click me</div>');
|
||||
var div = make('<div kt-patch="/test">click me</div>');
|
||||
div.click();
|
||||
this.server.respond();
|
||||
div.innerHTML.should.equal("patch");
|
||||
@@ -34,7 +34,7 @@ describe("HTMx AJAX Verbs", function() {
|
||||
|
||||
it('handles basic delete properly', function () {
|
||||
this.server.respondWith("DELETE", "/test", "delete");
|
||||
var div = make('<div hx-delete="/test">click me</div>');
|
||||
var div = make('<div kt-delete="/test">click me</div>');
|
||||
div.click();
|
||||
this.server.respond();
|
||||
div.innerHTML.should.equal("delete");
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
const pluginSyntaxHighlight = require("@11ty/eleventy-plugin-syntaxhighlight");
|
||||
const pluginSass = require("eleventy-plugin-sass");
|
||||
|
||||
module.exports = function(config) {
|
||||
config.addPlugin(pluginSyntaxHighlight);
|
||||
config.addPassthroughCopy("js");
|
||||
config.addPassthroughCopy("css");
|
||||
config.addPassthroughCopy("img");
|
||||
config.addPassthroughCopy("_");
|
||||
}
|
||||
config.addPlugin(pluginSass, {});
|
||||
}
|
||||
|
||||
52
www/_includes/core_layout.njk
Normal file
52
www/_includes/core_layout.njk
Normal file
@@ -0,0 +1,52 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>kutty - high power tools for html</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="/css/site.css"/>
|
||||
<link rel="stylesheet" href="/css/prism-theme.css"/>
|
||||
<script src="/js/htmx.js"></script>
|
||||
<script>
|
||||
kutty.logger = function(elt, event, data) {
|
||||
if(console) {
|
||||
console.log(event, elt, data);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="top-nav">
|
||||
<div class="c">
|
||||
<div class="row">
|
||||
<div class="2 col">
|
||||
<span class="logo light" kt-add-class="settle"><<a>/</a>> k<a>u</a>tty</span>
|
||||
</div>
|
||||
<div class="10 col nav">
|
||||
<div class="row">
|
||||
<div class="1 col">
|
||||
<a href="/">home</a>
|
||||
</div>
|
||||
<div class="1 col">
|
||||
<a href="/docs">docs</a>
|
||||
</div>
|
||||
<div class="1 col">
|
||||
<a href="/docs/attributes">attributes</a>
|
||||
</div>
|
||||
<div class="1 col">
|
||||
<a href="/docs/attributes">events</a>
|
||||
</div>
|
||||
<div class="1 col">
|
||||
<a href="/docs/attributes">headers</a>
|
||||
</div>
|
||||
<div class="1 col">
|
||||
<a href="https://github.com/bigskysoftware/kutty">github</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ content | safe }}
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,52 +1,6 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>HTMx - teaching good ol' HTML some new tricks</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="/css/site.css"/>
|
||||
<link rel="stylesheet" href="/css/prism-theme.css"/>
|
||||
<script src="/js/htmx.js"></script>
|
||||
<script>
|
||||
HTMx.logger = function(elt, event, data) {
|
||||
if(console) {
|
||||
console.log(event, elt, data);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="c">
|
||||
<div class="{% if page.url == '/' %}root{% endif %} top-nav">
|
||||
<h1 class="hero" hx-add-class="settle"><<a>/</a>> HTM<sub><a>x</a></sub>
|
||||
<svg onclick="document.getElementById('main-nav').classList.toggle('show')" class="hamburger" viewBox="0 0 100 80" width="30" height="30" style="margin-bottom:-8px">
|
||||
<rect width="100" height="20" style="fill:rgb(52, 101, 164)" rx="10"></rect>
|
||||
<rect y="30" width="100" height="20" style="fill:rgb(52, 101, 164)" rx="10"></rect>
|
||||
<rect y="60" width="100" height="20" style="fill:rgb(52, 101, 164)" rx="10"></rect>
|
||||
</svg>
|
||||
</h1>
|
||||
<div id="main-nav" class="row center nav collapse" hx-boost="true">
|
||||
<div class="1 col">
|
||||
<a href="/">home</a>
|
||||
</div>
|
||||
<div class="1 col">
|
||||
<a href="/docs">docs</a>
|
||||
</div>
|
||||
<div class="1 col">
|
||||
<a href="/docs/attributes">attributes</a>
|
||||
</div>
|
||||
<div class="1 col">
|
||||
<a href="/docs/attributes">events</a>
|
||||
</div>
|
||||
<div class="1 col">
|
||||
<a href="/docs/attributes">headers</a>
|
||||
</div>
|
||||
<div class="1 col">
|
||||
<a href="https://github.com/bigskysoftware/htmx">github</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="content">
|
||||
{{ content | safe }}
|
||||
</div>
|
||||
---
|
||||
layout: core_layout.njk
|
||||
---
|
||||
<div class="content c">
|
||||
{{ content | safe }}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,19 +1,47 @@
|
||||
$mainBlue: #3465a4;
|
||||
$lightBlue: #3d72d7;
|
||||
|
||||
body {
|
||||
margin: 0px;
|
||||
line-height: 1.6;
|
||||
line-height: 1.4em;
|
||||
font-size: 18px;
|
||||
color: #333;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
|
||||
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif !important;
|
||||
}
|
||||
|
||||
h2 {
|
||||
border-bottom: 2px solid whitesmoke;
|
||||
color: rgb(52, 101, 164);
|
||||
.logo {
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#content {
|
||||
margin-top: 32px
|
||||
.light {
|
||||
}
|
||||
|
||||
.top-nav {
|
||||
line-height: 30px;
|
||||
border-bottom: 1px solid whitesmoke;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.dark-hero {
|
||||
background-image: linear-gradient(#1f1f1f, #2d2d2d);
|
||||
height: 240px;
|
||||
line-height: 240px;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
vertical-align: center;
|
||||
color: whitesmoke;
|
||||
.logo {
|
||||
font-size: 100px;
|
||||
}
|
||||
a {
|
||||
color: $lightBlue;
|
||||
}
|
||||
box-shadow:
|
||||
inset 0px 11px 8px -10px #262626,
|
||||
inset 0px -11px 8px -10px #262626;
|
||||
border-bottom: 1px solid whitesmoke;
|
||||
}
|
||||
|
||||
p {
|
||||
@@ -43,22 +71,28 @@ blockquote {
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color:rgb(52, 101, 164)
|
||||
color: $mainBlue
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.nav ul {
|
||||
list-style: none;
|
||||
padding-left: 12px;
|
||||
.nav {
|
||||
ul {
|
||||
list-style: none;
|
||||
padding-left: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.hamburger {
|
||||
display: none;
|
||||
}
|
||||
|
||||
h2:not(:first-of-type) {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
/* customized version of lit.css */
|
||||
* + *{
|
||||
box-sizing: border-box;
|
||||
@@ -110,7 +144,7 @@ a {
|
||||
|
||||
.card:focus {
|
||||
outline: 0;
|
||||
border: solid rgb(52, 101, 164);
|
||||
border: solid $mainBlue;
|
||||
}
|
||||
|
||||
hr {
|
||||
@@ -134,8 +168,8 @@ a[href]:hover, .btn:hover {
|
||||
|
||||
.btn.primary {
|
||||
color: white;
|
||||
background: rgb(52, 101, 164);
|
||||
border: solid rgb(52, 101, 164);
|
||||
background: $mainBlue;
|
||||
border: solid $mainBlue;
|
||||
}
|
||||
|
||||
td {
|
||||
141
www/docs.md
141
www/docs.md
@@ -34,12 +34,12 @@ title: HTMx - HTML Extensions
|
||||
</div>
|
||||
<div class="10 col">
|
||||
|
||||
## <a name="introduction"></a>[HTMx in a Nutshell](#introduction)
|
||||
## <a name="introduction"></a>[Kutty in a Nutshell](#introduction)
|
||||
|
||||
HTMx is a set of attributes that allow you to access modern browser features directly from HTML, rather than using
|
||||
Kutty is a library that allows you to access modern browser features directly from HTML, rather than using
|
||||
javascript.
|
||||
|
||||
To understand how HTMx works, first lets take a look at an anchor tag:
|
||||
To understand kutty, first lets take a look at an anchor tag:
|
||||
|
||||
``` html
|
||||
<a href="/blog">Blog</a>
|
||||
@@ -50,59 +50,60 @@ This anchor tag tells a browser:
|
||||
> "When a user clicks on this link, issue an HTTP GET request to '/blog' and load the response content
|
||||
> into the browser window".
|
||||
|
||||
With that in mind, consider the following HTMx code:
|
||||
With that in mind, consider the following bit of HTML:
|
||||
|
||||
``` html
|
||||
<div hx-post="/clicked">Click Me!</div>
|
||||
<div kt-post="/clicked">Click Me!</div>
|
||||
```
|
||||
|
||||
This tells a browser:
|
||||
This tells kutty:
|
||||
|
||||
> "When a user clicks on this div, issue an HTTP POST request to '/clicked' and load the response content into the inner
|
||||
> html of this element"
|
||||
|
||||
So the difference is that with HTMx:
|
||||
So kutty extends the basic idea of that anchor tag:
|
||||
|
||||
* Any element can issue a HTTP request
|
||||
* Any event can trigger the request (not just clicks or form submissions)
|
||||
* The HTTP request is done via AJAX
|
||||
* Different HTTP verbs can used
|
||||
* The response replaces the content of the element, rather than the entire page
|
||||
|
||||
HTMx expects responses to the AJAX calls that it makes to be *HTML* rather than *JSON*, as is more typical with AJAX
|
||||
requests.
|
||||
When you are using kutty, you respond to the AJAX calls with *HTML* rather than *JSON*, often a small amount of
|
||||
HTML rather than the whole page.
|
||||
|
||||
If you prefer it, you can use the `data-` prefix when using HTMx:
|
||||
If you prefer, you can use the `data-` prefix when using kutty:
|
||||
|
||||
``` html
|
||||
<a data-hx-post="/click">Click Me!</a>
|
||||
<a data-kt-post="/click">Click Me!</a>
|
||||
```
|
||||
|
||||
## <a name="installing"></a> [Installing](#installing)
|
||||
|
||||
HTMx is a dependency-free javascript library.
|
||||
|
||||
It can be used via [NPM](https://www.npmjs.com/) as "`htmx.org`" or downloaded or included
|
||||
from [unpkg](https://unpkg.com/browse/htmx.org/):
|
||||
It can be used via [NPM](https://www.npmjs.com/) as "`kutty.org`" or downloaded or included
|
||||
from [unpkg](https://unpkg.com/browse/kutty.org/):
|
||||
|
||||
``` html
|
||||
<script src="https://unpkg.com/htmx.org@0.0.1"></script>
|
||||
<script src="https://unpkg.com/kutty.org@0.0.1"></script>
|
||||
```
|
||||
|
||||
## <a name="ajax"></a> [AJAX](#ajax)
|
||||
|
||||
One of the primary features HTMx provides are attributes to allow you to issue AJAX requests directly from HTML:
|
||||
|
||||
* [hx-get](/attributes/hx-get) - Issues a `GET` request to the given URL
|
||||
* [hx-post](/attributes/hx-post) - Issues a `POST` request to the given URL
|
||||
* [hx-put](/attributes/hx-put) - Issues a `PUT` request to the given URL (see [details](#htmx-request-details))
|
||||
* [hx-patch](/attributes/hx-patch) - Issues a `PATCH` request to the given URL (see [details](#htmx-request-details))
|
||||
* [hx-delete](/attributes/hx-delete) - Issues a `GET` request to the given URL (see [details](#htmx-request-details))
|
||||
* [kt-get](/attributes/kt-get) - Issues a `GET` request to the given URL
|
||||
* [kt-post](/attributes/kt-post) - Issues a `POST` request to the given URL
|
||||
* [kt-put](/attributes/kt-put) - Issues a `PUT` request to the given URL (see [details](#htmx-request-details))
|
||||
* [kt-patch](/attributes/kt-patch) - Issues a `PATCH` request to the given URL (see [details](#htmx-request-details))
|
||||
* [kt-delete](/attributes/kt-delete) - Issues a `GET` request to the given URL (see [details](#htmx-request-details))
|
||||
|
||||
Each of these attributes takes a URL to issue an AJAX request to. The element will issue a request of the specified
|
||||
type to the given URL when the element is [triggered](#triggers):
|
||||
|
||||
```html
|
||||
<div hx-put="/messages">Put To Messages</div>
|
||||
<div kt-put="/messages">Put To Messages</div>
|
||||
```
|
||||
|
||||
This tells the browser:
|
||||
@@ -117,40 +118,40 @@ By default AJAX requests are triggered by the "natural" event of an element:
|
||||
* `form`: the `submit` event
|
||||
* everything else: the `click` event
|
||||
|
||||
If you don't want the request to happen on the default event, you can use the [hx-trigger](/attributes/hx-trigger)
|
||||
If you don't want the request to happen on the default event, you can use the [kt-trigger](/attributes/kt-trigger)
|
||||
attribute to specify the event of interest. Here is a `div` that posts to `/mouse_entered`
|
||||
when a mouse enters it:
|
||||
|
||||
```html
|
||||
<div hx-post="/mouse_entered" hx-trigger="mouseenter">
|
||||
<div kt-post="/mouse_entered" kt-trigger="mouseenter">
|
||||
[Here Mouse, Mouse!]
|
||||
</div>
|
||||
```
|
||||
|
||||
If you want a request to only happen once, you can use the [hx-trigger-once](/attributes/hx-trigger-once) attribute:
|
||||
If you want a request to only happen once, you can use the [kt-trigger-once](/attributes/kt-trigger-once) attribute:
|
||||
|
||||
```html
|
||||
<div hx-post="/mouse_entered" hx-trigger="mouseenter"
|
||||
hx-trigger-once="true">
|
||||
<div kt-post="/mouse_entered" kt-trigger="mouseenter"
|
||||
kt-trigger-once="true">
|
||||
[Here Mouse, Mouse!]
|
||||
</div>
|
||||
```
|
||||
|
||||
There are two additional modifiers you can use for trigger:
|
||||
|
||||
* [hx-trigger-changed-only](/attributes/hx-trigger-changed-only) - when set to `true` the element will only issue a
|
||||
* [kt-trigger-changed-only](/attributes/kt-trigger-changed-only) - when set to `true` the element will only issue a
|
||||
request if its value has changed
|
||||
* [hx-trigger-delay](/attributes/hx-trigger-delay) - tells HTMx to wait the given amount of time (e.g. `1s`) before
|
||||
* [kt-trigger-delay](/attributes/kt-trigger-delay) - tells HTMx to wait the given amount of time (e.g. `1s`) before
|
||||
issuing the request. If the event triggers again, the countdown is reset.
|
||||
|
||||
You can use these two attributes to implement a common UX pattern, [Live Search](/demo/live-search):
|
||||
|
||||
```html
|
||||
<input type="text" name="q"
|
||||
hx-get="/trigger_delay"
|
||||
hx-trigger="keyup"
|
||||
hx-target="#search-results"
|
||||
hx-trigger-delay="500ms" placeholder="Search..."/>
|
||||
kt-get="/trigger_delay"
|
||||
kt-trigger="keyup"
|
||||
kt-target="#search-results"
|
||||
kt-trigger-delay="500ms" placeholder="Search..."/>
|
||||
<div id="search-results"></div>
|
||||
```
|
||||
|
||||
@@ -159,7 +160,7 @@ into the `div#search-results`.
|
||||
|
||||
#### <a name="special-events"></a> [Special Events](#special-events)
|
||||
|
||||
HTMx provides a few special events for use in [hx-trigger](/attributes/hx-trigger):
|
||||
HTMx provides a few special events for use in [kt-trigger](/attributes/kt-trigger):
|
||||
|
||||
* `load` - fires once when the element is first loaded
|
||||
* `revealed` - fires once when an element first scrolls into the viewport
|
||||
@@ -171,7 +172,7 @@ You can also use custom events to trigger requests if you have an advanced use c
|
||||
If you want an element to poll the given URL rather than wait for an event, you can use the `every` syntax:
|
||||
|
||||
```html
|
||||
<div hx-get="/news" trigger="every 2s"></div>
|
||||
<div kt-get="/news" trigger="every 2s"></div>
|
||||
```
|
||||
|
||||
This tells HTMx
|
||||
@@ -186,7 +187,7 @@ server and the browser than websockets.
|
||||
|
||||
If you want an element to respond to a Server Sent Event via HTMx, you need to do two things:
|
||||
|
||||
1. Define an SSE source. To do this, add a [hx-sse-src](/attributes/hx-sse-src) attribute on a parent element
|
||||
1. Define an SSE source. To do this, add a [kt-sse-src](/attributes/kt-sse-src) attribute on a parent element
|
||||
that specifies the URL from which Server Sent Events will be received.
|
||||
|
||||
2. Specify the Server Sent Event that will trigger the element, with the prefix `sse:`
|
||||
@@ -194,8 +195,8 @@ that specifies the URL from which Server Sent Events will be received.
|
||||
Here is an example:
|
||||
|
||||
```html
|
||||
<body hx-sse-src="/sse_messages">
|
||||
<div trigger="sse:new_news" hx-get="/news"></div>
|
||||
<body kt-sse-src="/sse_messages">
|
||||
<div trigger="sse:new_news" kt-get="/news"></div>
|
||||
</body>
|
||||
```
|
||||
|
||||
@@ -205,33 +206,33 @@ notify the div if there was new news to get, rather than the steady requests tha
|
||||
### <a name="indicators"></a> [Request Indicators](#indicators)
|
||||
|
||||
When an AJAX request is issued it is often good to let the user know that something is happening, since the browser
|
||||
will not give them any feedback. You can accomplish this in HTMx by using the [hx-indicator](/attributes/hx-indicator)
|
||||
attribute, the `hx-show-indicator` class and some CSS.
|
||||
will not give them any feedback. You can accomplish this in HTMx by using the [kt-indicator](/attributes/kt-indicator)
|
||||
attribute, the `kutty-show-indicator` class and some CSS.
|
||||
|
||||
By default the `hx-show-indicator` class will be put on the element issuing the request. This can be used to show a
|
||||
By default the `kutty-show-indicator` class will be put on the element issuing the request. This can be used to show a
|
||||
spinner gif, for example:
|
||||
|
||||
```html
|
||||
<style>
|
||||
.indicator { display: none }
|
||||
.hx-show-indicator .indicator { display: inline }
|
||||
.kutty-show-indicator .indicator { display: inline }
|
||||
</style>
|
||||
<button hx-get="/click">
|
||||
<button kt-get="/click">
|
||||
Click Me!
|
||||
<img class="indicator" src="/spinner.gif"/>
|
||||
</button>
|
||||
```
|
||||
|
||||
If you want the `hx-show-indicator` class added to a different element, you can use the [hx-indicator](/attributes/hx-indicator)
|
||||
If you want the `kutty-show-indicator` class added to a different element, you can use the [kt-indicator](/attributes/kt-indicator)
|
||||
attribute with a CSS selector to do so:
|
||||
|
||||
```html
|
||||
<style>
|
||||
.indicator { display: none }
|
||||
.hx-show-indicator .indicator { display: inline }
|
||||
.kutty-show-indicator .indicator { display: inline }
|
||||
</style>
|
||||
<div id="parent-div">
|
||||
<button hx-get="/click" hx-indicator="#parent-div">
|
||||
<button kt-get="/click" kt-indicator="#parent-div">
|
||||
Click Me!
|
||||
</button>
|
||||
<img class="indicator" src="/spinner.gif"/>
|
||||
@@ -240,14 +241,14 @@ attribute with a CSS selector to do so:
|
||||
### <a name="targets"></a> [Targets](#targets)
|
||||
|
||||
If you want the response to be loaded into a different element other than the one that made the request, you can
|
||||
use the [hx-target](/attributes/hx-target) attribute, which takes a CSS selector. Looking back at our Live Search example:
|
||||
use the [kt-target](/attributes/kt-target) attribute, which takes a CSS selector. Looking back at our Live Search example:
|
||||
|
||||
```html
|
||||
<input type="text" name="q"
|
||||
hx-get="/trigger_delay"
|
||||
hx-trigger="keyup"
|
||||
hx-target="#search-results"
|
||||
hx-trigger-delay="500ms" placeholder="Search..."/>
|
||||
kt-get="/trigger_delay"
|
||||
kt-trigger="keyup"
|
||||
kt-target="#search-results"
|
||||
kt-trigger-delay="500ms" placeholder="Search..."/>
|
||||
<div id="search-results"></div>
|
||||
```
|
||||
|
||||
@@ -257,7 +258,7 @@ input tag.
|
||||
### <a name="swapping"></a> [Swapping](#swapping)
|
||||
|
||||
HTMx offers a few different ways to swap the HTML returned into the DOM. By default, the content replaces the
|
||||
`innerHTML` of the target element. You can modify this by using the [hx-swap](/attributes/hx-swap) attribute
|
||||
`innerHTML` of the target element. You can modify this by using the [kt-swap](/attributes/kt-swap) attribute
|
||||
with any of the following values:
|
||||
|
||||
* `innerHTML` - the default, puts the content inside the target element
|
||||
@@ -270,10 +271,10 @@ with any of the following values:
|
||||
#### Out of Band Swaps
|
||||
|
||||
If you want to swap content from a response directly into the DOM by using the `id` attribute you can use the
|
||||
[hx-swap-oob](/attributes/hx-swap-oob) attribute in the *response* html:
|
||||
[kt-swap-oob](/attributes/kt-swap-oob) attribute in the *response* html:
|
||||
|
||||
```html
|
||||
<div id="message" hx-swap-oob="true">Swap me directly!</div>
|
||||
<div id="message" kt-swap-oob="true">Swap me directly!</div>
|
||||
Additional Content
|
||||
```
|
||||
|
||||
@@ -286,7 +287,7 @@ Note that out of band elements must be in the top level of the response, and not
|
||||
|
||||
#### Selecting Content To Swap
|
||||
|
||||
If you want to select a subset of the response HTML to swap into the target, you can use the [hx-select](/attributes/hx-select)
|
||||
If you want to select a subset of the response HTML to swap into the target, you can use the [kt-select](/attributes/kt-select)
|
||||
attribute, which takes a CSS selector and selects the matching elements from the response.
|
||||
|
||||
### <a name="forms"></a> [Forms & Input Values](#forms)
|
||||
@@ -294,7 +295,7 @@ attribute, which takes a CSS selector and selects the matching elements from the
|
||||
By default, an element will include its value if it has one. Additionally, if the element is in a form, all values
|
||||
in the form will be included in the request.
|
||||
|
||||
If you wish to include the values of other elements, you can use the [hx-include](/attributes/hx-include) attribute
|
||||
If you wish to include the values of other elements, you can use the [kt-include](/attributes/kt-include) attribute
|
||||
with a CSS selector of all the elements whose values you want to include in the request.
|
||||
|
||||
Finally, if you want to programatically modify the arguments, you can use the [values.hx](/events/values.hx) event to
|
||||
@@ -305,10 +306,10 @@ do so.
|
||||
HTMx provides a simple mechanism for interacting with the [browser history API](https://developer.mozilla.org/en-US/docs/Web/API/History_API):
|
||||
|
||||
If you want a given element to push its request into the browser navigation bar and add the current state of the page
|
||||
to the browser's history, include the [hx-push](/attributes/hx-push) attribute:
|
||||
to the browser's history, include the [kt-push](/attributes/kt-push) attribute:
|
||||
|
||||
```html
|
||||
<a hx-get="/Blog" hx-push="true">Blog</a>
|
||||
<a kt-get="/Blog" kt-push="true">Blog</a>
|
||||
```
|
||||
|
||||
When a user clicks on this link, HTMx will snapshot the current DOM and store it before it makes a request to /blog.
|
||||
@@ -320,7 +321,7 @@ When a user hits the back button, HTMx will retrieve the old content from storag
|
||||
### Specifying History Snapshot Element
|
||||
|
||||
By default, HTMx will use the `body` to take and restore the history snapshop from. This is usually the right thing, but
|
||||
if you want to use a narrower element for snapshotting you can use the [hx-history-element](/attributes/hx-history-element)
|
||||
if you want to use a narrower element for snapshotting you can use the [kt-history-element](/attributes/kt-history-element)
|
||||
attribute to specify a different one.
|
||||
|
||||
Careful: this element will need to be on all pages or restoring from history won't work reliably.
|
||||
@@ -331,22 +332,22 @@ Careful: this element will need to be on all pages or restoring from history won
|
||||
|
||||
HTMx includes a number of useful headers in requests:
|
||||
|
||||
* `X-HX-Request` - will be set to "true"
|
||||
* `X-HX-Trigger-Id` - will be set to the id of the element that triggered the request
|
||||
* `X-HX-Trigger-Name` - will be set to the name of the element that triggered the request
|
||||
* `X-HX-Target-Id` - will be set to the id of the target element
|
||||
* `X-HX-Current-URL` - will be set to the URL of the browser
|
||||
* `X-HX-Prompt` - will be set to the value entered by the user when prompted via [hx-prompt](/attributes/hx-prompt)
|
||||
* `X-HX-Event-Target` - the id of the original target of the event that triggered the request
|
||||
* `X-HX-Active-Element` - the id of the current active element
|
||||
* `X-HX-Active-Element-Value` - the value of the current active element
|
||||
* `X-KT-Request` - will be set to "true"
|
||||
* `X-KT-Trigger-Id` - will be set to the id of the element that triggered the request
|
||||
* `X-KT-Trigger-Name` - will be set to the name of the element that triggered the request
|
||||
* `X-KT-Target-Id` - will be set to the id of the target element
|
||||
* `X-KT-Current-URL` - will be set to the URL of the browser
|
||||
* `X-KT-Prompt` - will be set to the value entered by the user when prompted via [kt-prompt](/attributes/kt-prompt)
|
||||
* `X-KT-Event-Target` - the id of the original target of the event that triggered the request
|
||||
* `X-KT-Active-Element` - the id of the current active element
|
||||
* `X-KT-Active-Element-Value` - the value of the current active element
|
||||
|
||||
### Response Headers
|
||||
|
||||
HTMx supports two special response headers:
|
||||
|
||||
* `X-HX-Trigger` - can be used to trigger client side events, see the [documentation](/events/x-hx-trigger) for examples.
|
||||
* `X-HX-Push` - can be used to push a new URL into the browsers address bar
|
||||
* `X-KT-Trigger` - can be used to trigger client side events, see the [documentation](/events/X-KT-trigger) for examples.
|
||||
* `X-KT-Push` - can be used to push a new URL into the browsers address bar
|
||||
|
||||
### Request Order of Operations
|
||||
|
||||
@@ -354,9 +355,9 @@ The order of operations in a HTMx request are:
|
||||
|
||||
* The element is triggered and begins a request
|
||||
* Values are gathered for the request
|
||||
* The `hx-show-indicator` class is applied to the appropriate elements
|
||||
* The `kutty-show-indicator` class is applied to the appropriate elements
|
||||
* The request is then issued asynchronously via AJAX
|
||||
* Upon getting a response the target element is marked with the `hx-swapping` class
|
||||
* Upon getting a response the target element is marked with the `kutty-swapping` class
|
||||
* An optional swap delay is done (default: no delay)
|
||||
* The actual content swap is done
|
||||
* A settle delay is done (default: 100ms)
|
||||
|
||||
@@ -13,15 +13,15 @@ title: HTMx - HTML Extensions / Attributes
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>hx-get</td>
|
||||
<td>kt-get</td>
|
||||
<td>Issues an HTTP GET to the given URL</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>hx-target</td>
|
||||
<td>kt-target</td>
|
||||
<td>Specifies the target element that should be swapped</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>hx-swap</td>
|
||||
<td>kt-swap</td>
|
||||
<td>Specifies how target element should be swapped: innerHTML, outerHTML, append</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
BIN
www/img/kutty_placeholder.png
Normal file
BIN
www/img/kutty_placeholder.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
32
www/index.md
32
www/index.md
@@ -1,29 +1,37 @@
|
||||
---
|
||||
layout: layout.njk
|
||||
layout: core_layout.njk
|
||||
title: HTMx - HTML Extensions
|
||||
---
|
||||
|
||||
<div class="dark-hero">
|
||||
<span class="logo dark" kt-add-class="settle"><<a>/</a>> k<a>u</a>tty</span>
|
||||
<sub><i>high powered tools for HTML</i></sub>
|
||||
</div>
|
||||
|
||||
<div class="c">
|
||||
|
||||
## Introduction
|
||||
|
||||
HTMx is a small (<12Kb) & dependency-free library that surfaces the features of modern browsers using HTML
|
||||
attributes. Using HTMx you can implement many [UX patterns](/demo) that would typically require writing javascript.
|
||||
Kutty is a set of HTML extensions (attributes, request headers, etc.) that allow you to use markup to build
|
||||
[powerful UX](/demo), while keeping the simplicity of the hypertext we all know and love.
|
||||
|
||||
HTMx is unobtrusive, plays well with other tools, can be adopted incrementally with no up-front rewrites.
|
||||
Kutty is a small (<6Kb min.gz'd), dependency-free, and can be adopted incrementally without a huge rewrite.
|
||||
|
||||
## Quick Start
|
||||
|
||||
``` html
|
||||
<!-- Load from unpkg -->
|
||||
<script src="https://unpkg.com/htmx.org@0.0.1"></script>
|
||||
|
||||
<!-- enhance a button -->
|
||||
<button hx-get="/example">Click Me</button>
|
||||
<script src="https://unpkg.com/kutty.org@0.0.1"></script>
|
||||
<!-- have a button POST a click via AJAX -->
|
||||
<button kt-post="/clicked" kt-swap="outerHTML">Click Me</button>
|
||||
```
|
||||
|
||||
This code tells HTMx that:
|
||||
This annotation tells kutty:
|
||||
|
||||
> "When a user clicks on this button, issue an AJAX request to /example, and load the content into the body
|
||||
> of the button"
|
||||
> "When a user clicks on this button, issue an AJAX request to /example, and replace the button with the response"
|
||||
|
||||
HTMx is based on [intercooler.js](http://intercoolerjs.org) and is the successor to that project.
|
||||
|
||||
|
||||
Kutty is based on [intercooler.js](http://intercoolerjs.org) and is the successor to that project.
|
||||
|
||||
</div>
|
||||
@@ -1,5 +1,5 @@
|
||||
// noinspection JSUnusedAssignment
|
||||
var HTMx = HTMx || (function () {
|
||||
var kutty = kutty || (function () {
|
||||
'use strict';
|
||||
|
||||
var VERBS = ['get', 'post', 'put', 'delete', 'patch']
|
||||
@@ -24,7 +24,7 @@ var HTMx = HTMx || (function () {
|
||||
return elt.getAttribute && elt.getAttribute(name);
|
||||
}
|
||||
|
||||
// resolve with both hx and data-hx prefixes
|
||||
// resolve with both kt and data-kt prefixes
|
||||
function getAttributeValue(elt, qualifiedName) {
|
||||
return getRawAttribute(elt, qualifiedName) || getRawAttribute(elt, "data-" + qualifiedName);
|
||||
}
|
||||
@@ -87,7 +87,7 @@ var HTMx = HTMx || (function () {
|
||||
}
|
||||
|
||||
function getInternalData(elt) {
|
||||
var dataProp = 'hx-data-internal';
|
||||
var dataProp = 'kutty-internal-data';
|
||||
var data = elt[dataProp];
|
||||
if (!data) {
|
||||
data = elt[dataProp] = {};
|
||||
@@ -129,9 +129,9 @@ var HTMx = HTMx || (function () {
|
||||
//====================================================================
|
||||
|
||||
function getTarget(elt) {
|
||||
var explicitTarget = getClosestMatch(elt, function(e){return getRawAttribute(e,"hx-target") !== null});
|
||||
var explicitTarget = getClosestMatch(elt, function(e){return getRawAttribute(e,"kt-target") !== null});
|
||||
if (explicitTarget) {
|
||||
var targetStr = getRawAttribute(explicitTarget, "hx-target");
|
||||
var targetStr = getRawAttribute(explicitTarget, "kt-target");
|
||||
if (targetStr === "this") {
|
||||
return explicitTarget;
|
||||
} else {
|
||||
@@ -161,7 +161,7 @@ var HTMx = HTMx || (function () {
|
||||
function handleOutOfBandSwaps(fragment) {
|
||||
var settleTasks = [];
|
||||
forEach(fragment.children, function(child){
|
||||
if (getAttributeValue(child, "hx-swap-oob") === "true") {
|
||||
if (getAttributeValue(child, "kt-swap-oob") === "true") {
|
||||
var target = getDocument().getElementById(child.id);
|
||||
if (target) {
|
||||
var fragment = new DocumentFragment()
|
||||
@@ -169,7 +169,7 @@ var HTMx = HTMx || (function () {
|
||||
settleTasks = settleTasks.concat(swapOuterHTML(target, fragment));
|
||||
} else {
|
||||
child.parentNode.removeChild(child);
|
||||
triggerEvent(getDocument().body, "oobErrorNoTarget.hx", {id:child.id, content:child})
|
||||
triggerEvent(getDocument().body, "oobErrorNoTarget.kutty", {id:child.id, content:child})
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -197,7 +197,7 @@ var HTMx = HTMx || (function () {
|
||||
var child = fragment.firstChild;
|
||||
parentNode.insertBefore(child, insertBefore);
|
||||
if (child.nodeType !== Node.TEXT_NODE) {
|
||||
triggerEvent(child, 'load.hx', {elt:child, parent:parentElt(child)});
|
||||
triggerEvent(child, 'load.kutty', {elt:child, parent:parentElt(child)});
|
||||
processNode(child);
|
||||
}
|
||||
}
|
||||
@@ -243,7 +243,7 @@ var HTMx = HTMx || (function () {
|
||||
}
|
||||
|
||||
function maybeSelectFromResponse(elt, fragment) {
|
||||
var selector = getClosestAttributeValue(elt, "hx-select");
|
||||
var selector = getClosestAttributeValue(elt, "kt-select");
|
||||
if (selector) {
|
||||
var newFragment = new DocumentFragment();
|
||||
forEach(fragment.querySelectorAll(selector), function (node) {
|
||||
@@ -260,7 +260,7 @@ var HTMx = HTMx || (function () {
|
||||
|
||||
fragment = maybeSelectFromResponse(elt, fragment);
|
||||
|
||||
var swapStyle = getClosestAttributeValue(elt, "hx-swap");
|
||||
var swapStyle = getClosestAttributeValue(elt, "kt-swap");
|
||||
switch(swapStyle) {
|
||||
case "outerHTML": return concat(settleTasks, swapOuterHTML(target, fragment));
|
||||
case "prepend": return concat(settleTasks, swapPrepend(target, fragment));
|
||||
@@ -291,7 +291,7 @@ var HTMx = HTMx || (function () {
|
||||
}
|
||||
|
||||
function getTrigger(elt) {
|
||||
var explicitTrigger = getClosestAttributeValue(elt, 'hx-trigger');
|
||||
var explicitTrigger = getClosestAttributeValue(elt, 'kt-trigger');
|
||||
if (explicitTrigger) {
|
||||
return explicitTrigger;
|
||||
} else {
|
||||
@@ -337,7 +337,7 @@ var HTMx = HTMx || (function () {
|
||||
nodeData.timeout = setTimeout(function () {
|
||||
if (bodyContains(elt)) {
|
||||
issueAjaxRequest(elt, verb, path);
|
||||
processPolling(elt, verb, getAttributeValue(elt, "hx-" + verb));
|
||||
processPolling(elt, verb, getAttributeValue(elt, "kt-" + verb));
|
||||
}
|
||||
}, interval);
|
||||
}
|
||||
@@ -373,14 +373,14 @@ var HTMx = HTMx || (function () {
|
||||
var elementData = getInternalData(elt);
|
||||
if (!eventData.handled) {
|
||||
eventData.handled = true;
|
||||
if (getAttributeValue(elt, "hx-trigger-once") === "true") {
|
||||
if (getAttributeValue(elt, "kt-trigger-once") === "true") {
|
||||
if (elementData.triggeredOnce) {
|
||||
return;
|
||||
} else {
|
||||
elementData.triggeredOnce = true;
|
||||
}
|
||||
}
|
||||
if (getAttributeValue(elt, "hx-trigger-changed-only") === "true") {
|
||||
if (getAttributeValue(elt, "kt-trigger-changed-only") === "true") {
|
||||
if (elementData.lastValue === elt.value) {
|
||||
return;
|
||||
} else {
|
||||
@@ -390,7 +390,7 @@ var HTMx = HTMx || (function () {
|
||||
if (elementData.delayed) {
|
||||
clearTimeout(elementData.delayed);
|
||||
}
|
||||
var eventDelay = getAttributeValue(elt, "hx-trigger-delay");
|
||||
var eventDelay = getAttributeValue(elt, "kt-trigger-delay");
|
||||
var issueRequest = function(){
|
||||
issueAjaxRequest(elt, verb, path, evt.target);
|
||||
}
|
||||
@@ -407,13 +407,13 @@ var HTMx = HTMx || (function () {
|
||||
}
|
||||
|
||||
function initScrollHandler() {
|
||||
if (!window['hxScrollHandler']) {
|
||||
if (!window['kuttyScrollHandler']) {
|
||||
var scrollHandler = function() {
|
||||
forEach(getDocument().querySelectorAll("[hx-trigger='reveal']"), function (elt) {
|
||||
forEach(getDocument().querySelectorAll("[kt-trigger='reveal']"), function (elt) {
|
||||
maybeReveal(elt);
|
||||
});
|
||||
};
|
||||
window['hxScrollHandler'] = scrollHandler;
|
||||
window['kuttyScrollHandler'] = scrollHandler;
|
||||
window.addEventListener("scroll", scrollHandler)
|
||||
}
|
||||
}
|
||||
@@ -438,10 +438,10 @@ var HTMx = HTMx || (function () {
|
||||
initializer: function() { new EventSource(sseSrc, details.config) },
|
||||
config:{withCredentials: true}
|
||||
};
|
||||
triggerEvent(elt, "initSSE.mx", {config:details})
|
||||
triggerEvent(elt, "initSSE.kutty", {config:details})
|
||||
var source = details.initializer();
|
||||
source.onerror = function (e) {
|
||||
triggerEvent(elt, "sseError.mx", {error:e, source:source});
|
||||
triggerEvent(elt, "sseError.kutty", {error:e, source:source});
|
||||
maybeCloseSSESource(elt);
|
||||
};
|
||||
getInternalData(elt).sseSource = source;
|
||||
@@ -463,7 +463,7 @@ var HTMx = HTMx || (function () {
|
||||
};
|
||||
sseSource.sseSource.addEventListener(sseEventName, sseListener);
|
||||
} else {
|
||||
triggerEvent(elt, "noSSESourceError.mx")
|
||||
triggerEvent(elt, "noSSESourceError.kutty")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -477,7 +477,7 @@ var HTMx = HTMx || (function () {
|
||||
function processVerbs(elt, nodeData, trigger) {
|
||||
var explicitAction = false;
|
||||
forEach(VERBS, function (verb) {
|
||||
var path = getAttributeValue(elt, 'hx-' + verb);
|
||||
var path = getAttributeValue(elt, 'kt-' + verb);
|
||||
if (path) {
|
||||
explicitAction = true;
|
||||
nodeData.path = path;
|
||||
@@ -508,18 +508,18 @@ var HTMx = HTMx || (function () {
|
||||
var trigger = getTrigger(elt);
|
||||
var explicitAction = processVerbs(elt, nodeData, trigger);
|
||||
|
||||
if (!explicitAction && getClosestAttributeValue(elt, "hx-boost") === "true") {
|
||||
if (!explicitAction && getClosestAttributeValue(elt, "kt-boost") === "true") {
|
||||
boostElement(elt, nodeData, trigger);
|
||||
}
|
||||
var sseSrc = getAttributeValue(elt, 'hx-sse-source');
|
||||
var sseSrc = getAttributeValue(elt, 'kt-sse-source');
|
||||
if (sseSrc) {
|
||||
initSSESource(elt, sseSrc);
|
||||
}
|
||||
var addClass = getAttributeValue(elt, 'hx-add-class');
|
||||
var addClass = getAttributeValue(elt, 'kt-add-class');
|
||||
if (addClass) {
|
||||
processClassList(elt, addClass, "add");
|
||||
}
|
||||
var removeClass = getAttributeValue(elt, 'hx-remove-class');
|
||||
var removeClass = getAttributeValue(elt, 'kt-remove-class');
|
||||
if (removeClass) {
|
||||
processClassList(elt, removeClass, "remove");
|
||||
}
|
||||
@@ -532,7 +532,7 @@ var HTMx = HTMx || (function () {
|
||||
//====================================================================
|
||||
|
||||
function sendError(elt, eventName, details) {
|
||||
var errorURL = getClosestAttributeValue(elt, "hx-error-url");
|
||||
var errorURL = getClosestAttributeValue(elt, "kt-error-url");
|
||||
if (errorURL) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", errorURL);
|
||||
@@ -555,22 +555,22 @@ var HTMx = HTMx || (function () {
|
||||
function triggerEvent(elt, eventName, details) {
|
||||
details["elt"] = elt;
|
||||
var event = makeEvent(eventName, details);
|
||||
if (HTMx.logger) {
|
||||
HTMx.logger(elt, eventName, details);
|
||||
if (kutty.logger) {
|
||||
kutty.logger(elt, eventName, details);
|
||||
if (eventName.indexOf("Error") > 0) {
|
||||
sendError(elt, eventName, details);
|
||||
}
|
||||
}
|
||||
var eventResult = elt.dispatchEvent(event);
|
||||
var allResult = elt.dispatchEvent(makeEvent("all.hx", {elt:elt, originalDetails:details, originalEvent: event}));
|
||||
var allResult = elt.dispatchEvent(makeEvent("all.kutty", {elt:elt, originalDetails:details, originalEvent: event}));
|
||||
return eventResult && allResult;
|
||||
}
|
||||
|
||||
function addHTMxEventListener(arg1, arg2, arg3) {
|
||||
function addKuttyEventListener(arg1, arg2, arg3) {
|
||||
var target, event, listener;
|
||||
if (isFunction(arg1)) {
|
||||
target = getDocument().body;
|
||||
event = "all.hx";
|
||||
event = "all.kutty";
|
||||
listener = arg1;
|
||||
} else if (isFunction(arg2)) {
|
||||
target = getDocument().body;
|
||||
@@ -588,7 +588,7 @@ var HTMx = HTMx || (function () {
|
||||
// History Support
|
||||
//====================================================================
|
||||
function getHistoryElement() {
|
||||
var historyElt = getDocument().querySelector('.hx-history-element');
|
||||
var historyElt = getDocument().querySelector('.kt-history-element');
|
||||
return historyElt || getDocument().body;
|
||||
}
|
||||
|
||||
@@ -607,21 +607,21 @@ var HTMx = HTMx || (function () {
|
||||
}
|
||||
|
||||
function bumpHistoryAccessDate(pathAndSearch) {
|
||||
var historyTimestamps = JSON.parse(localStorage.getItem("hx-history-timestamps")) || {};
|
||||
var historyTimestamps = JSON.parse(localStorage.getItem("kt-history-timestamps")) || {};
|
||||
historyTimestamps[pathAndSearch] = Date.now();
|
||||
var paths = Object.keys(historyTimestamps);
|
||||
if (paths.length > 20) {
|
||||
purgeOldestPaths(paths, historyTimestamps);
|
||||
}
|
||||
localStorage.setItem("hx-history-timestamps", JSON.stringify(historyTimestamps));
|
||||
localStorage.setItem("kt-history-timestamps", JSON.stringify(historyTimestamps));
|
||||
}
|
||||
|
||||
function saveHistory() {
|
||||
var elt = getHistoryElement();
|
||||
var pathAndSearch = location.pathname+location.search;
|
||||
triggerEvent(getDocument().body, "historyUpdate.hx", {path:pathAndSearch, historyElement:elt});
|
||||
triggerEvent(getDocument().body, "historyUpdate.kutty", {path:pathAndSearch, historyElement:elt});
|
||||
history.replaceState({}, getDocument().title, window.location.href);
|
||||
localStorage.setItem('hx-history:' + pathAndSearch, elt.innerHTML);
|
||||
localStorage.setItem('kt-history:' + pathAndSearch, elt.innerHTML);
|
||||
bumpHistoryAccessDate(pathAndSearch);
|
||||
}
|
||||
|
||||
@@ -636,14 +636,14 @@ var HTMx = HTMx || (function () {
|
||||
}
|
||||
|
||||
function loadHistoryFromServer(pathAndSearch) {
|
||||
triggerEvent(getDocument().body, "historyCacheMiss.hx", {path: pathAndSearch});
|
||||
triggerEvent(getDocument().body, "historyCacheMiss.kutty", {path: pathAndSearch});
|
||||
var request = new XMLHttpRequest();
|
||||
request.open('GET', pathAndSearch, true);
|
||||
request.onload = function () {
|
||||
triggerEvent(getDocument().body, "historyCacheMissLoad.hx", {path: pathAndSearch});
|
||||
triggerEvent(getDocument().body, "historyCacheMissLoad.kutty", {path: pathAndSearch});
|
||||
if (this.status >= 200 && this.status < 400) {
|
||||
var fragment = makeFragment(this.response);
|
||||
fragment = fragment.querySelector('.hx-history-element') || fragment;
|
||||
fragment = fragment.querySelector('.kt-history-element') || fragment;
|
||||
settleImmediately(swapInnerHTML(getHistoryElement(), fragment));
|
||||
}
|
||||
};
|
||||
@@ -651,8 +651,8 @@ var HTMx = HTMx || (function () {
|
||||
|
||||
function restoreHistory() {
|
||||
var pathAndSearch = location.pathname+location.search;
|
||||
triggerEvent(getDocument().body, "historyRestore.hx", {path:pathAndSearch});
|
||||
var content = localStorage.getItem('hx-history:' + pathAndSearch);
|
||||
triggerEvent(getDocument().body, "historyRestore.kutty", {path:pathAndSearch});
|
||||
var content = localStorage.getItem('kt-history:' + pathAndSearch);
|
||||
if (content) {
|
||||
bumpHistoryAccessDate(pathAndSearch);
|
||||
settleImmediately(swapInnerHTML(getHistoryElement(), makeFragment(content)));
|
||||
@@ -662,7 +662,7 @@ var HTMx = HTMx || (function () {
|
||||
}
|
||||
|
||||
function shouldPush(elt) {
|
||||
return getClosestAttributeValue(elt, "hx-push-url") === "true" ||
|
||||
return getClosestAttributeValue(elt, "kt-push-url") === "true" ||
|
||||
(elt.tagName === "A" && getInternalData(elt).boosted);
|
||||
}
|
||||
|
||||
@@ -675,14 +675,14 @@ var HTMx = HTMx || (function () {
|
||||
}
|
||||
|
||||
function mutateRequestIndicatorClasses(elt, action) {
|
||||
var indicator = getClosestAttributeValue(elt, 'hx-indicator');
|
||||
var indicator = getClosestAttributeValue(elt, 'kt-indicator');
|
||||
if (indicator) {
|
||||
var indicators = getDocument().querySelectorAll(indicator);
|
||||
} else {
|
||||
indicators = [elt];
|
||||
}
|
||||
forEach(indicators, function(ic) {
|
||||
ic.classList[action].call(ic.classList, "hx-show-indicator");
|
||||
ic.classList[action].call(ic.classList, "kutty-show-indicator");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -735,7 +735,7 @@ var HTMx = HTMx || (function () {
|
||||
processInputValue(processed, values, elt);
|
||||
|
||||
// include any explicit includes
|
||||
var includes = getAttributeValue(elt, "hx-include");
|
||||
var includes = getAttributeValue(elt, "kt-include");
|
||||
if (includes) {
|
||||
var nodes = getDocument().querySelectorAll(includes);
|
||||
forEach(nodes, function(node) {
|
||||
@@ -778,7 +778,28 @@ var HTMx = HTMx || (function () {
|
||||
//====================================================================
|
||||
|
||||
function setHeader(xhr, name, value, noPrefix) {
|
||||
xhr.setRequestHeader((noPrefix ? "" : "X-HX-") + name, value || "");
|
||||
xhr.setRequestHeader((noPrefix ? "" : "X-KT-") + name, value || "");
|
||||
}
|
||||
|
||||
function setRequestHeaders(xhr, elt, target, prompt, eventTarget) {
|
||||
setHeader(xhr, "Request", "true");
|
||||
setHeader(xhr, "Trigger-Id", getRawAttribute(elt, "id"));
|
||||
setHeader(xhr, "Trigger-Name", getRawAttribute(elt, "name"));
|
||||
setHeader(xhr, "Target-Id", getRawAttribute(target, "id"));
|
||||
setHeader(xhr, "Current-URL", getDocument().location.href);
|
||||
if (prompt) {
|
||||
setHeader(xhr, "Prompt", prompt);
|
||||
}
|
||||
if (eventTarget) {
|
||||
setHeader(xhr, "Event-Target", getRawAttribute(eventTarget, "id"));
|
||||
}
|
||||
if (getDocument().activeElement) {
|
||||
setHeader(xhr, "Active-Element", getRawAttribute(getDocument().activeElement, "id"));
|
||||
// noinspection JSUnresolvedVariable
|
||||
if (getDocument().activeElement.value) {
|
||||
setHeader(xhr, "Active-Element-Value", getDocument().activeElement.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function issueAjaxRequest(elt, verb, path, eventTarget) {
|
||||
@@ -792,13 +813,13 @@ var HTMx = HTMx || (function () {
|
||||
eltData.requestInFlight = false
|
||||
}
|
||||
var target = getTarget(elt);
|
||||
var promptQuestion = getClosestAttributeValue(elt, "hx-prompt");
|
||||
var promptQuestion = getClosestAttributeValue(elt, "kt-prompt");
|
||||
if (promptQuestion) {
|
||||
var prompt = prompt(promptQuestion);
|
||||
if(!triggerEvent(elt, 'prompt.hx', {prompt: prompt, target:target})) return endRequestLock();
|
||||
if(!triggerEvent(elt, 'prompt.kutty', {prompt: prompt, target:target})) return endRequestLock();
|
||||
}
|
||||
|
||||
var confirmQuestion = getClosestAttributeValue(elt, "hx-confirm");
|
||||
var confirmQuestion = getClosestAttributeValue(elt, "kt-confirm");
|
||||
if (confirmQuestion) {
|
||||
if(!confirm(confirmQuestion)) return endRequestLock();
|
||||
}
|
||||
@@ -806,7 +827,7 @@ var HTMx = HTMx || (function () {
|
||||
var xhr = new XMLHttpRequest();
|
||||
|
||||
var inputValues = getInputValues(elt);
|
||||
if(!triggerEvent(elt, 'values.hx', {values: inputValues, target:target})) return endRequestLock();
|
||||
if(!triggerEvent(elt, 'values.kutty', {values: inputValues, target:target})) return endRequestLock();
|
||||
|
||||
// request type
|
||||
var requestURL;
|
||||
@@ -827,31 +848,14 @@ var HTMx = HTMx || (function () {
|
||||
xhr.overrideMimeType("text/html");
|
||||
|
||||
// request headers
|
||||
setHeader(xhr, "Request", "true");
|
||||
setHeader(xhr,"Trigger-Id", getRawAttribute(elt,"id"));
|
||||
setHeader(xhr,"Trigger-Name", getRawAttribute(elt, "name"));
|
||||
setHeader(xhr,"Target-Id", getRawAttribute(target,"id"));
|
||||
setHeader(xhr,"Current-URL", getDocument().location.href);
|
||||
if (prompt) {
|
||||
setHeader(xhr,"Prompt", prompt);
|
||||
}
|
||||
if (eventTarget) {
|
||||
setHeader(xhr,"Event-Target", getRawAttribute(eventTarget,"id"));
|
||||
}
|
||||
if (getDocument().activeElement) {
|
||||
setHeader(xhr,"Active-Element", getRawAttribute(getDocument().activeElement,"id"));
|
||||
// noinspection JSUnresolvedVariable
|
||||
if (getDocument().activeElement.value) {
|
||||
setHeader(xhr,"Active-Element-Value", getDocument().activeElement.value);
|
||||
}
|
||||
}
|
||||
setRequestHeaders(xhr, elt, target, prompt, eventTarget);
|
||||
|
||||
xhr.onload = function () {
|
||||
try {
|
||||
if (!triggerEvent(elt, 'beforeOnLoad.hx', {xhr: xhr, target: target})) return;
|
||||
if (!triggerEvent(elt, 'beforeOnLoad.kutty', {xhr: xhr, target: target})) return;
|
||||
|
||||
handleTrigger(elt, this.getResponseHeader("X-HX-Trigger"));
|
||||
var pushedUrl = this.getResponseHeader("X-HX-Push")
|
||||
handleTrigger(elt, this.getResponseHeader("X-KT-Trigger"));
|
||||
var pushedUrl = this.getResponseHeader("X-KT-Push")
|
||||
|
||||
var shouldSaveHistory = shouldPush(elt) || pushedUrl;
|
||||
|
||||
@@ -860,47 +864,47 @@ var HTMx = HTMx || (function () {
|
||||
if (this.status !== 204) {
|
||||
// Success!
|
||||
var resp = this.response;
|
||||
if (!triggerEvent(elt, 'beforeSwap.hx', {xhr: xhr, target: target})) return;
|
||||
if (!triggerEvent(elt, 'beforeSwap.kutty', {xhr: xhr, target: target})) return;
|
||||
|
||||
// Save current page
|
||||
if (shouldSaveHistory) {
|
||||
saveHistory();
|
||||
}
|
||||
|
||||
target.classList.add("hx-swapping");
|
||||
target.classList.add("kutty-swapping");
|
||||
var doSwap = function () {
|
||||
try {
|
||||
var settleTasks = swapResponse(target, elt, resp);
|
||||
target.classList.remove("hx-swapping");
|
||||
target.classList.add("hx-settling");
|
||||
triggerEvent(elt, 'afterSwap.hx', {xhr: xhr, target: target});
|
||||
target.classList.remove("kutty-swapping");
|
||||
target.classList.add("kutty-settling");
|
||||
triggerEvent(elt, 'afterSwap.kutty', {xhr: xhr, target: target});
|
||||
|
||||
var doSettle = function(){
|
||||
forEach(settleTasks, function (settleTask) {
|
||||
settleTask.call();
|
||||
});
|
||||
target.classList.remove("hx-settling");
|
||||
target.classList.remove("kutty-settling");
|
||||
// push URL and save new page
|
||||
if (shouldSaveHistory) {
|
||||
pushUrlIntoHistory(pushedUrl || requestURL );
|
||||
saveHistory();
|
||||
}
|
||||
triggerEvent(elt, 'afterSettle.hx', {xhr: xhr, target: target});
|
||||
triggerEvent(elt, 'afterSettle.kutty', {xhr: xhr, target: target});
|
||||
}
|
||||
|
||||
var settleDelayStr = getAttributeValue(elt, "hx-settle-delay") || "100ms";
|
||||
var settleDelayStr = getAttributeValue(elt, "kt-settle-delay") || "100ms";
|
||||
if (settleDelayStr) {
|
||||
setTimeout(doSettle, parseInterval(settleDelayStr))
|
||||
} else {
|
||||
doSettle();
|
||||
}
|
||||
} catch (e) {
|
||||
triggerEvent(elt, 'swapError.hx', {xhr: xhr, response: xhr.response, status: xhr.status, target: target});
|
||||
triggerEvent(elt, 'swapError.kutty', {xhr: xhr, response: xhr.response, status: xhr.status, target: target});
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
var swapDelayStr = getAttributeValue(elt, "hx-swap-delay");
|
||||
var swapDelayStr = getAttributeValue(elt, "kt-swap-delay");
|
||||
if (swapDelayStr) {
|
||||
setTimeout(doSwap, parseInterval(swapDelayStr))
|
||||
} else {
|
||||
@@ -908,22 +912,22 @@ var HTMx = HTMx || (function () {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
triggerEvent(elt, 'responseError.hx', {xhr: xhr, response: xhr.response, status: xhr.status, target: target});
|
||||
triggerEvent(elt, 'responseError.kutty', {xhr: xhr, response: xhr.response, status: xhr.status, target: target});
|
||||
}
|
||||
} catch (e) {
|
||||
triggerEvent(elt, 'onLoadError.hx', {xhr: xhr, response: xhr.response, status: xhr.status, target: target});
|
||||
triggerEvent(elt, 'onLoadError.kutty', {xhr: xhr, response: xhr.response, status: xhr.status, target: target});
|
||||
throw e;
|
||||
} finally {
|
||||
removeRequestIndicatorClasses(elt);
|
||||
endRequestLock();
|
||||
triggerEvent(elt, 'afterOnLoad.hx', {xhr: xhr, response: xhr.response, status: xhr.status, target: target});
|
||||
triggerEvent(elt, 'afterOnLoad.kutty', {xhr: xhr, response: xhr.response, status: xhr.status, target: target});
|
||||
}
|
||||
}
|
||||
xhr.onerror = function () {
|
||||
removeRequestIndicatorClasses(elt);triggerEvent(elt, 'loadError.hx', {xhr:xhr});
|
||||
removeRequestIndicatorClasses(elt);triggerEvent(elt, 'loadError.kutty', {xhr:xhr});
|
||||
endRequestLock();
|
||||
}
|
||||
if(!triggerEvent(elt, 'beforeRequest.hx', {xhr:xhr, values: inputValues, target:target})) return endRequestLock();
|
||||
if(!triggerEvent(elt, 'beforeRequest.kutty', {xhr:xhr, values: inputValues, target:target})) return endRequestLock();
|
||||
addRequestIndicatorClasses(elt);
|
||||
xhr.send(verb === 'get' ? null : urlEncode(inputValues));
|
||||
}
|
||||
@@ -955,8 +959,8 @@ var HTMx = HTMx || (function () {
|
||||
// Public API
|
||||
return {
|
||||
processElement: processNode,
|
||||
on: addHTMxEventListener,
|
||||
version: "0.0.2",
|
||||
on: addKuttyEventListener,
|
||||
version: "0.0.1",
|
||||
_:internalEval
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user