mirror of
https://github.com/bigskysoftware/htmx.git
synced 2025-09-28 21:41:40 +00:00
update website
This commit is contained in:
parent
d08110ed22
commit
3b84f86319
@ -23,7 +23,7 @@
|
||||
<div class="c">
|
||||
<div class="row">
|
||||
<div class="2 col" kt-get="/" kt-target="body" kt-push-url="true">
|
||||
<span class="logo light" kt-add-class="settle"><<a>/</a>> k<a>u</a>tty</span>
|
||||
<span class="logo light"><<a>/</a>> k<a>u</a>tty</span>
|
||||
</div>
|
||||
{% if page.url.indexOf("/patterns/") == 0 %}
|
||||
<div class="10 col nav"> <!-- don't boost on demo pages, sinon hijacks everything :/ -->
|
||||
|
@ -3,7 +3,7 @@ layout: layout.njk
|
||||
title: </> kutty - high power tools for html
|
||||
---
|
||||
|
||||
<div class="dark-hero full-width" kt-add-class="appear">
|
||||
<div class="dark-hero full-width" kt-classes="add appear">
|
||||
<span class="logo dark"><<a>/</a>> <span class="no-mobile">k<a>u</a>tty</span></span>
|
||||
<sub class="no-mobile"><i>high powered tools for HTML</i></sub>
|
||||
</div>
|
||||
|
284
www/js/kutty.js
284
www/js/kutty.js
@ -118,6 +118,10 @@ var kutty = kutty || (function () {
|
||||
return arr1.concat(arr2);
|
||||
}
|
||||
|
||||
function splitOnWhitespace(trigger) {
|
||||
return trigger.split(/\s+/);
|
||||
}
|
||||
|
||||
//====================================================================
|
||||
// Node processing
|
||||
//====================================================================
|
||||
@ -208,19 +212,19 @@ var kutty = kutty || (function () {
|
||||
}
|
||||
}
|
||||
|
||||
function swapPrepend(target, fragment) {
|
||||
function swapAfterBegin(target, fragment) {
|
||||
return insertNodesBefore(target, target.firstChild, fragment);
|
||||
}
|
||||
|
||||
function swapPrependBefore(target, fragment) {
|
||||
function swapBeforeBegin(target, fragment) {
|
||||
return insertNodesBefore(parentElt(target), target, fragment);
|
||||
}
|
||||
|
||||
function swapAppend(target, fragment) {
|
||||
function swapBeforeEnd(target, fragment) {
|
||||
return insertNodesBefore(target, null, fragment);
|
||||
}
|
||||
|
||||
function swapAppendAfter(target, fragment) {
|
||||
function swapAfterEnd(target, fragment) {
|
||||
return insertNodesBefore(parentElt(target), target.nextSibling, fragment);
|
||||
}
|
||||
|
||||
@ -248,20 +252,19 @@ var kutty = kutty || (function () {
|
||||
return fragment;
|
||||
}
|
||||
|
||||
function swapResponse(target, elt, responseText) {
|
||||
function swapResponse(swapStyle, target, elt, responseText) {
|
||||
var fragment = makeFragment(responseText);
|
||||
if (fragment) {
|
||||
var settleTasks = handleOutOfBandSwaps(fragment);
|
||||
|
||||
fragment = maybeSelectFromResponse(elt, fragment);
|
||||
|
||||
var swapStyle = getClosestAttributeValue(elt, "kt-swap");
|
||||
switch(swapStyle) {
|
||||
case "outerHTML": return concat(settleTasks, swapOuterHTML(target, fragment));
|
||||
case "prepend": return concat(settleTasks, swapPrepend(target, fragment));
|
||||
case "prependBefore": return concat(settleTasks, swapPrependBefore(target, fragment));
|
||||
case "append": return concat(settleTasks, swapAppend(target, fragment));
|
||||
case "appendAfter": return concat(settleTasks, swapAppendAfter(target, fragment));
|
||||
case "afterbegin": return concat(settleTasks, swapAfterBegin(target, fragment));
|
||||
case "beforebegin": return concat(settleTasks, swapBeforeBegin(target, fragment));
|
||||
case "beforeend": return concat(settleTasks, swapBeforeEnd(target, fragment));
|
||||
case "afterend": return concat(settleTasks, swapAfterEnd(target, fragment));
|
||||
default: return concat(settleTasks, swapInnerHTML(target, fragment));
|
||||
}
|
||||
}
|
||||
@ -286,58 +289,104 @@ var kutty = kutty || (function () {
|
||||
}
|
||||
}
|
||||
|
||||
function getTrigger(elt) {
|
||||
function getTriggerSpec(elt) {
|
||||
|
||||
var triggerSpec = {
|
||||
"trigger" : "click"
|
||||
}
|
||||
var explicitTrigger = getClosestAttributeValue(elt, 'kt-trigger');
|
||||
if (explicitTrigger) {
|
||||
return explicitTrigger;
|
||||
} else {
|
||||
if (matches(elt, 'button')) {
|
||||
return 'click';
|
||||
} else if (matches(elt, 'form')) {
|
||||
return 'submit';
|
||||
} else if (matches(elt, 'input, textarea, select')) {
|
||||
return 'change';
|
||||
} else {
|
||||
return 'click';
|
||||
var tokens = splitOnWhitespace(explicitTrigger);
|
||||
if (tokens.length > 0) {
|
||||
var trigger = tokens[0];
|
||||
if (trigger === "every") {
|
||||
triggerSpec.pollInterval = parseInterval(tokens[1]);
|
||||
} else if (trigger.indexOf("sse:") === 0) {
|
||||
triggerSpec.sseEvent = trigger.substr(4);
|
||||
} else {
|
||||
triggerSpec['trigger'] = trigger;
|
||||
for (var i = 1; i < tokens.length; i++) {
|
||||
var token = tokens[i].trim();
|
||||
if (token === "changed") {
|
||||
triggerSpec.changed = true;
|
||||
}
|
||||
if (token === "once") {
|
||||
triggerSpec.once = true;
|
||||
}
|
||||
if (token.indexOf("delay:") === 0) {
|
||||
triggerSpec.delay = parseInterval(token.substr(6));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (matches(elt, 'form')) {
|
||||
triggerSpec['trigger'] = 'submit';
|
||||
} else if (matches(elt, 'input, textarea, select')) {
|
||||
triggerSpec['trigger'] = 'change';
|
||||
}
|
||||
}
|
||||
return triggerSpec;
|
||||
}
|
||||
|
||||
function parseClassOperation(trimmedValue) {
|
||||
var split = splitOnWhitespace(trimmedValue);
|
||||
if (split.length > 1) {
|
||||
var operation = split[0];
|
||||
var classDef = split[1].trim();
|
||||
var cssClass;
|
||||
var delay;
|
||||
if (classDef.indexOf(":") > 0) {
|
||||
var splitCssClass = classDef.split(':');
|
||||
cssClass = splitCssClass[0];
|
||||
delay = parseInterval(splitCssClass[1]);
|
||||
} else {
|
||||
cssClass = classDef;
|
||||
delay = 100;
|
||||
}
|
||||
return {
|
||||
operation:operation,
|
||||
cssClass:cssClass,
|
||||
delay:delay
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function processClassList(elt, classList, operation) {
|
||||
var values = classList.split(",");
|
||||
forEach(values, function(value){
|
||||
var cssClass = "";
|
||||
var delay = 50;
|
||||
var trimmedValue = value.trim();
|
||||
if (trimmedValue.indexOf(":") > 0) {
|
||||
var split = trimmedValue.split(':');
|
||||
cssClass = split[0];
|
||||
delay = parseInterval(split[1]);
|
||||
} else {
|
||||
cssClass = trimmedValue;
|
||||
}
|
||||
setTimeout(function () {
|
||||
elt.classList[operation].call(elt.classList, cssClass);
|
||||
}, delay);
|
||||
forEach(classList.split("&"), function (run) {
|
||||
var currentRunTime = 0;
|
||||
forEach(run.split(","), function(value){
|
||||
var trimmedValue = value.trim();
|
||||
var classOperation = parseClassOperation(trimmedValue);
|
||||
if (classOperation) {
|
||||
if (classOperation.operation === "toggle") {
|
||||
setTimeout(function () {
|
||||
setInterval(function () {
|
||||
elt.classList[classOperation.operation].call(elt.classList, classOperation.cssClass);
|
||||
}, classOperation.delay);
|
||||
}, currentRunTime);
|
||||
currentRunTime = currentRunTime + classOperation.delay;
|
||||
} else {
|
||||
currentRunTime = currentRunTime + classOperation.delay;
|
||||
setTimeout(function () {
|
||||
elt.classList[classOperation.operation].call(elt.classList, classOperation.cssClass);
|
||||
}, currentRunTime);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function processPolling(elt, verb, path) {
|
||||
var trigger = getTrigger(elt);
|
||||
function processPolling(elt, verb, path, interval) {
|
||||
var nodeData = getInternalData(elt);
|
||||
if (trigger.trim().indexOf("every ") === 0) {
|
||||
var args = trigger.split(/\s+/);
|
||||
var intervalStr = args[1];
|
||||
if (intervalStr) {
|
||||
var interval = parseInterval(intervalStr);
|
||||
nodeData.timeout = setTimeout(function () {
|
||||
if (bodyContains(elt)) {
|
||||
issueAjaxRequest(elt, verb, path);
|
||||
processPolling(elt, verb, getAttributeValue(elt, "kt-" + verb));
|
||||
}
|
||||
}, interval);
|
||||
nodeData.timeout = setTimeout(function () {
|
||||
if (bodyContains(elt)) {
|
||||
issueAjaxRequest(elt, verb, path);
|
||||
processPolling(elt, verb, getAttributeValue(elt, "kt-" + verb), interval);
|
||||
}
|
||||
}
|
||||
}, interval);
|
||||
}
|
||||
|
||||
function isLocalLink(elt) {
|
||||
@ -346,7 +395,7 @@ var kutty = kutty || (function () {
|
||||
!getRawAttribute(elt,'href').startsWith("#")
|
||||
}
|
||||
|
||||
function boostElement(elt, nodeData, trigger) {
|
||||
function boostElement(elt, nodeData, triggerSpec) {
|
||||
if ((elt.tagName === "A" && isLocalLink(elt)) || elt.tagName === "FORM") {
|
||||
nodeData.boosted = true;
|
||||
var verb, path;
|
||||
@ -358,31 +407,31 @@ var kutty = kutty || (function () {
|
||||
verb = rawAttribute ? rawAttribute.toLowerCase() : "get";
|
||||
path = getRawAttribute(elt, 'action');
|
||||
}
|
||||
addEventListener(elt, verb, path, nodeData, trigger, true);
|
||||
addEventListener(elt, verb, path, nodeData, triggerSpec, true);
|
||||
}
|
||||
}
|
||||
|
||||
function shouldCancel(elt) {
|
||||
return elt.tagName === "FORM" ||
|
||||
(matches(elt, 'input[type="submit"], button') && closest(elt, 'form') !== null) ||
|
||||
(elt.tagName === "A" && elt.href && elt.href.indexOf('#') != 0);
|
||||
(elt.tagName === "A" && elt.href && elt.href.indexOf('#') !== 0);
|
||||
}
|
||||
|
||||
function addEventListener(elt, verb, path, nodeData, trigger, explicitCancel) {
|
||||
function addEventListener(elt, verb, path, nodeData, triggerSpec, explicitCancel) {
|
||||
var eventListener = function (evt) {
|
||||
if(explicitCancel || shouldCancel(elt)) evt.preventDefault();
|
||||
var eventData = getInternalData(evt);
|
||||
var elementData = getInternalData(elt);
|
||||
if (!eventData.handled) {
|
||||
eventData.handled = true;
|
||||
if (getAttributeValue(elt, "kt-trigger-once") === "true") {
|
||||
if (triggerSpec.once) {
|
||||
if (elementData.triggeredOnce) {
|
||||
return;
|
||||
} else {
|
||||
elementData.triggeredOnce = true;
|
||||
}
|
||||
}
|
||||
if (getAttributeValue(elt, "kt-trigger-changed-only") === "true") {
|
||||
if (triggerSpec.changed) {
|
||||
if (elementData.lastValue === elt.value) {
|
||||
return;
|
||||
} else {
|
||||
@ -392,20 +441,19 @@ var kutty = kutty || (function () {
|
||||
if (elementData.delayed) {
|
||||
clearTimeout(elementData.delayed);
|
||||
}
|
||||
var eventDelay = getAttributeValue(elt, "kt-trigger-delay");
|
||||
var issueRequest = function(){
|
||||
issueAjaxRequest(elt, verb, path, evt.target);
|
||||
}
|
||||
if (eventDelay) {
|
||||
elementData.delayed = setTimeout(issueRequest, parseInterval(eventDelay));
|
||||
if (triggerSpec.delay) {
|
||||
elementData.delayed = setTimeout(issueRequest, parseInterval(triggerSpec.delay));
|
||||
} else {
|
||||
issueRequest();
|
||||
}
|
||||
}
|
||||
};
|
||||
nodeData.trigger = trigger;
|
||||
nodeData.trigger = triggerSpec.trigger;
|
||||
nodeData.eventListener = eventListener;
|
||||
elt.addEventListener(trigger, eventListener);
|
||||
elt.addEventListener(triggerSpec.trigger, eventListener);
|
||||
}
|
||||
|
||||
function initScrollHandler() {
|
||||
@ -476,7 +524,7 @@ var kutty = kutty || (function () {
|
||||
}
|
||||
}
|
||||
|
||||
function processVerbs(elt, nodeData, trigger) {
|
||||
function processVerbs(elt, nodeData, triggerSpec) {
|
||||
var explicitAction = false;
|
||||
forEach(VERBS, function (verb) {
|
||||
var path = getAttributeValue(elt, 'kt-' + verb);
|
||||
@ -484,18 +532,18 @@ var kutty = kutty || (function () {
|
||||
explicitAction = true;
|
||||
nodeData.path = path;
|
||||
nodeData.verb = verb;
|
||||
if (trigger.indexOf("sse:") === 0) {
|
||||
processSSETrigger(trigger.substr(4), elt, verb, path);
|
||||
} else if (trigger === 'revealed') {
|
||||
if (triggerSpec.sseEvent) {
|
||||
processSSETrigger(triggerSpec.sseEvent, elt, verb, path);
|
||||
} else if (triggerSpec.trigger === "revealed") {
|
||||
initScrollHandler();
|
||||
maybeReveal(elt);
|
||||
} else if (trigger === 'load') {
|
||||
} else if (triggerSpec.trigger === "load") {
|
||||
loadImmediately(nodeData, elt, verb, path);
|
||||
} else if (trigger.trim().indexOf('every ') === 0) {
|
||||
} else if (triggerSpec.pollInterval) {
|
||||
nodeData.polling = true;
|
||||
processPolling(elt, verb, path);
|
||||
processPolling(elt, verb, path, triggerSpec.pollInterval);
|
||||
} else {
|
||||
addEventListener(elt, verb, path, nodeData, trigger);
|
||||
addEventListener(elt, verb, path, nodeData, triggerSpec);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -507,23 +555,19 @@ var kutty = kutty || (function () {
|
||||
if (!nodeData.processed) {
|
||||
nodeData.processed = true;
|
||||
|
||||
var trigger = getTrigger(elt);
|
||||
var explicitAction = processVerbs(elt, nodeData, trigger);
|
||||
var triggerSpec = getTriggerSpec(elt);
|
||||
var explicitAction = processVerbs(elt, nodeData, triggerSpec);
|
||||
|
||||
if (!explicitAction && getClosestAttributeValue(elt, "kt-boost") === "true") {
|
||||
boostElement(elt, nodeData, trigger);
|
||||
boostElement(elt, nodeData, triggerSpec);
|
||||
}
|
||||
var sseSrc = getAttributeValue(elt, 'kt-sse-source');
|
||||
if (sseSrc) {
|
||||
initSSESource(elt, sseSrc);
|
||||
}
|
||||
var addClass = getAttributeValue(elt, 'kt-add-class');
|
||||
var addClass = getAttributeValue(elt, 'kt-classes');
|
||||
if (addClass) {
|
||||
processClassList(elt, addClass, "add");
|
||||
}
|
||||
var removeClass = getAttributeValue(elt, 'kt-remove-class');
|
||||
if (removeClass) {
|
||||
processClassList(elt, removeClass, "remove");
|
||||
processClassList(elt, addClass);
|
||||
}
|
||||
}
|
||||
if (elt.children) { // IE
|
||||
@ -598,7 +642,7 @@ var kutty = kutty || (function () {
|
||||
// History Support
|
||||
//====================================================================
|
||||
function getHistoryElement() {
|
||||
var historyElt = getDocument().querySelector('.kt-history-element');
|
||||
var historyElt = getDocument().querySelector('.kt-history-elt');
|
||||
return historyElt || getDocument().body;
|
||||
}
|
||||
|
||||
@ -653,7 +697,7 @@ var kutty = kutty || (function () {
|
||||
triggerEvent(getDocument().body, "historyCacheMissLoad.kutty", {path: pathAndSearch});
|
||||
if (this.status >= 200 && this.status < 400) {
|
||||
var fragment = makeFragment(this.response);
|
||||
fragment = fragment.querySelector('.kt-history-element') || fragment;
|
||||
fragment = fragment.querySelector('.kt-history-elt') || fragment;
|
||||
settleImmediately(swapInnerHTML(getHistoryElement(), fragment));
|
||||
}
|
||||
};
|
||||
@ -812,6 +856,61 @@ var kutty = kutty || (function () {
|
||||
}
|
||||
}
|
||||
|
||||
function filterValues(inputValues, elt, verb) {
|
||||
var paramsValue = getClosestAttributeValue(elt, "kt-params");
|
||||
if (paramsValue) {
|
||||
if (paramsValue === "none") {
|
||||
return {};
|
||||
} else if (paramsValue === "*") {
|
||||
return inputValues;
|
||||
} else if(paramsValue.indexOf("not ") === 0) {
|
||||
forEach(paramsValue.substr(4).split(","), function (value) {
|
||||
value = value.trim();
|
||||
delete inputValues[value];
|
||||
});
|
||||
return inputValues;
|
||||
} else {
|
||||
var newValues = {}
|
||||
forEach(paramsValue.split(","), function (value) {
|
||||
newValues[value] = inputValues[value];
|
||||
});
|
||||
return newValues;
|
||||
}
|
||||
} else {
|
||||
// By default GET does not include parameters
|
||||
if (verb === 'get') {
|
||||
return {};
|
||||
} else {
|
||||
return inputValues;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getSwapSpecification(elt) {
|
||||
var swapInfo = getClosestAttributeValue(elt, "kt-swap");
|
||||
var swapSpec = {
|
||||
"swapStyle" : "innerHTML",
|
||||
"swapDelay" : 0,
|
||||
"settleDelay" : 100
|
||||
}
|
||||
if (swapInfo) {
|
||||
var split = splitOnWhitespace(swapInfo);
|
||||
if (split.length > 0) {
|
||||
swapSpec["swapStyle"] = split[0];
|
||||
for (var i = 1; i < swapSpec.length; i++) {
|
||||
var modifier = swapSpec[i];
|
||||
if (modifier.indexOf("swap:") === 0) {
|
||||
swapSpec["swapDelay"] = parseInterval(modifier.substr(5));
|
||||
}
|
||||
if (modifier.indexOf("settle:") === 0) {
|
||||
swapSpec["settleDelay"] = parseInterval(modifier.substr(7));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return swapSpec;
|
||||
}
|
||||
|
||||
function issueAjaxRequest(elt, verb, path, eventTarget) {
|
||||
var eltData = getInternalData(elt);
|
||||
if (eltData.requestInFlight) {
|
||||
@ -836,16 +935,17 @@ var kutty = kutty || (function () {
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
|
||||
var inputValues = getInputValues(elt);
|
||||
var inputValues = getInputValues(elt, verb);
|
||||
|
||||
inputValues = filterValues(inputValues, elt, verb);
|
||||
|
||||
if(!triggerEvent(elt, 'values.kutty', {values: inputValues, target:target})) return endRequestLock();
|
||||
|
||||
// request type
|
||||
var requestURL;
|
||||
if (verb === 'get') {
|
||||
var includeQueryParams = getClosestAttributeValue("kt-get-params") === "true";
|
||||
// TODO allow get parameter filtering
|
||||
requestURL = path + (includeQueryParams ? "?" + urlEncode(inputValues) : "");
|
||||
xhr.open('GET', requestURL, true);
|
||||
var noValues = Object.keys(inputValues).length === 0;
|
||||
xhr.open('GET', path + (noValues ? "" : "?" + urlEncode(inputValues)), true);
|
||||
} else {
|
||||
requestURL = path;
|
||||
xhr.open('POST', requestURL, true);
|
||||
@ -882,10 +982,12 @@ var kutty = kutty || (function () {
|
||||
saveHistory();
|
||||
}
|
||||
|
||||
var swapSpec = getSwapSpecification(elt);
|
||||
|
||||
target.classList.add("kutty-swapping");
|
||||
var doSwap = function () {
|
||||
try {
|
||||
var settleTasks = swapResponse(target, elt, resp);
|
||||
var settleTasks = swapResponse(swapSpec.swapStyle, target, elt, resp);
|
||||
target.classList.remove("kutty-swapping");
|
||||
target.classList.add("kutty-settling");
|
||||
triggerEvent(elt, 'afterSwap.kutty', {xhr: xhr, target: target});
|
||||
@ -903,9 +1005,8 @@ var kutty = kutty || (function () {
|
||||
triggerEvent(elt, 'afterSettle.kutty', {xhr: xhr, target: target});
|
||||
}
|
||||
|
||||
var settleDelayStr = getAttributeValue(elt, "kt-settle-delay") || "100ms";
|
||||
if (settleDelayStr) {
|
||||
setTimeout(doSettle, parseInterval(settleDelayStr))
|
||||
if (swapSpec.settleDelay > 0) {
|
||||
setTimeout(doSettle, swapSpec.settleDelay)
|
||||
} else {
|
||||
doSettle();
|
||||
}
|
||||
@ -915,9 +1016,8 @@ var kutty = kutty || (function () {
|
||||
}
|
||||
};
|
||||
|
||||
var swapDelayStr = getAttributeValue(elt, "kt-swap-delay");
|
||||
if (swapDelayStr) {
|
||||
setTimeout(doSwap, parseInterval(swapDelayStr))
|
||||
if (swapSpec.swapDelay > 0) {
|
||||
setTimeout(doSwap, parseInterval(swapSpec.swapDelay))
|
||||
} else {
|
||||
doSwap();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user