small API and docs

This commit is contained in:
carson 2020-05-13 17:58:06 -07:00
parent 36bd9a25ca
commit 91fea14951
9 changed files with 342 additions and 150 deletions

12
TODO.md
View File

@ -6,9 +6,6 @@
## Launch TODOS
* Testing
* events
* X-KT-Trigger response header
* Blog Post
* Move to development branch
* Publish 0.0.1
@ -30,17 +27,8 @@
* ctrl-click on boosted anchors let's tab open normally
* `kutty-on="myEvent: ...""` attribute for handling custom events
* kutty javascript API
* find
* findAll
* closest
* remove
* sequence(op1, op2)
* add/remove/toggleClass
* trigger
* `kutty-requests` class on body
* local references (e.g. kt-get="#foo")
* polling cancellation API 205 code
* focus recapture
* Move to weakmap for kutty node info? https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap
* Scroll handler use https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API if available?

202
dist/kutty.js vendored
View File

@ -63,11 +63,6 @@ var kutty = kutty || (function () {
return matchesFunction && matchesFunction.call(elt, selector);
}
function closest(elt, selector) {
do if (elt == null || matches(elt, selector)) return elt;
while (elt = elt && parentElt(elt));
}
function getStartTag(str) {
var tagMatcher = /<([a-z][^\/\0>\x20\t\r\n\f]*)/i
var match = tagMatcher.exec( str );
@ -163,6 +158,119 @@ var kutty = kutty || (function () {
sheet.insertRule(rule, sheet.cssRules.length);
}
//==========================================================================================
// public API
//==========================================================================================
function internalEval(str){
return eval(str);
}
function onLoadHelper(callback) {
kutty.on("load.kutty", function(evt) {
callback(evt.detail.elt);
});
}
function logAll(){
kutty.logger = function(elt, event, data) {
if(console) {
console.log(event, elt, data);
}
}
}
function find(eltOrSelector, selector) {
if (selector) {
eltOrSelector.querySelector(eltOrSelector);
} else {
getDocument().body.querySelector(eltOrSelector);
}
}
function findAll(eltOrSelector, selector) {
if (selector) {
eltOrSelector.querySelectorAll(eltOrSelector);
} else {
getDocument().body.querySelectorAll(eltOrSelector);
}
}
function removeElement(elt, delay) {
if (delay) {
setTimeout(function(){removeElement(elt);}, delay)
} else {
elt.parentElement.removeChild(elt);
}
}
function addClassToElement(elt, clazz, delay) {
if (delay) {
setTimeout(function(){addClassToElement(elt, clazz);}, delay)
} else {
elt.classList.add(clazz);
}
}
function removeClassFromElement(elt, clazz) {
if (delay) {
setTimeout(function(){removeClassFromElement(elt, clazz);}, delay)
} else {
elt.classList.remove(clazz);
}
}
function toggleClassOnElement(elt, clazz) {
elt.classList.toggle(clazz);
}
function takeClassForElement(elt, clazz) {
forEach(elt.parent.children, function(child){
removeClassFromElement(child, clazz);
})
addClassToElement(elt, clazz);
}
function closest(elt, selector) {
do if (elt == null || matches(elt, selector)) return elt;
while (elt = elt && parentElt(elt));
}
function processEventArgs(arg1, arg2, arg3) {
if (isFunction(arg2)) {
return {
target: getDocument().body,
event: arg1,
listener: arg2
}
} else {
return {
target: arg1,
event: arg2,
listener: arg3
}
}
}
function addKuttyEventListener(arg1, arg2, arg3) {
var eventArgs = processEventArgs(arg1, arg2, arg3);
ready(function(){
eventArgs.target.addEventListener(eventArgs.event, eventArgs.listener);
})
return eventArgs.listener;
}
function removeKuttyEventListener(arg1, arg2, arg3) {
var eventArgs = processEventArgs(arg1, arg2, arg3);
ready(function(){
eventArgs.target.addEventListener(eventArgs.event, eventArgs.listener);
})
return eventArgs.listener;
}
//====================================================================
// Node processing
//====================================================================
@ -208,7 +316,7 @@ var kutty = kutty || (function () {
settleTasks = settleTasks.concat(swapOuterHTML(target, fragment));
} else {
child.parentNode.removeChild(child);
triggerEvent(getDocument().body, "oobErrorNoTarget.kutty", {content: child})
triggerErrorEvent(getDocument().body, "oobErrorNoTarget.kutty", {content: child})
}
}
});
@ -535,7 +643,7 @@ var kutty = kutty || (function () {
triggerEvent(elt, "initSSE.kutty", detail);
var source = new EventSource(sseSrc, detail.config);
source.onerror = function (e) {
triggerEvent(elt, "sseError.kutty", {error:e, source:source});
triggerErrorEvent(elt, "sseError.kutty", {error:e, source:source});
maybeCloseSSESource(elt);
};
getInternalData(elt).sseSource = source;
@ -557,7 +665,7 @@ var kutty = kutty || (function () {
};
sseSource.sseSource.addEventListener(sseEventName, sseListener);
} else {
triggerEvent(elt, "noSSESourceError.kutty")
triggerErrorEvent(elt, "noSSESourceError.kutty")
}
}
@ -651,42 +759,21 @@ var kutty = kutty || (function () {
return evt;
}
function triggerErrorEvent(elt, eventName, detail) {
triggerEvent(elt, eventName, Object.assign({isError:true}, details));
}
function triggerEvent(elt, eventName, detail) {
detail["elt"] = elt;
var event = makeEvent(eventName, detail);
if (kutty.logger) {
kutty.logger(elt, eventName, detail);
if (eventName.indexOf("Error") > 0) {
if (detail.isError) {
sendError(elt, eventName, detail);
}
}
var eventResult = elt.dispatchEvent(event);
var allResult = elt.dispatchEvent(makeEvent("all.kutty", {originalDetail:detail, originalEvent: event}));
return eventResult && allResult;
}
function addKuttyEventListener(arg1, arg2, arg3) {
var target, event, listener;
if (isFunction(arg1)) {
ready(function(){
target = getDocument().body;
event = "all.kutty";
listener = arg1;
target.addEventListener(event, listener);
})
} else if (isFunction(arg2)) {
ready(function () {
target = getDocument().body;
event = arg1;
listener = arg2;
target.addEventListener(event, listener);
})
} else {
target = arg1;
event = arg2;
listener = arg3;
target.addEventListener(event, listener);
}
return eventResult;
}
//====================================================================
@ -756,7 +843,7 @@ var kutty = kutty || (function () {
settleImmediately(swapInnerHTML(getHistoryElement(), fragment));
currentPathForHistory = path;
} else {
triggerEvent(getDocument().body, "historyCacheMissLoadError.kutty", details);
triggerErrorEvent(getDocument().body, "historyCacheMissLoadError.kutty", details);
}
};
request.send();
@ -992,7 +1079,7 @@ var kutty = kutty || (function () {
function issueAjaxRequest(elt, verb, path, eventTarget) {
var target = getTarget(elt);
if (target == null) {
triggerEvent(elt, 'targetError.kutty', {target: getRawAttribute(elt, "kt-target")});
triggerErrorEvent(elt, 'targetError.kutty', {target: getRawAttribute(elt, "kt-target")});
return;
}
var eltData = getInternalData(elt);
@ -1110,7 +1197,7 @@ var kutty = kutty || (function () {
doSettle();
}
} catch (e) {
triggerEvent(elt, 'swapError.kutty', eventDetail);
triggerErrorEvent(elt, 'swapError.kutty', eventDetail);
throw e;
}
};
@ -1122,11 +1209,11 @@ var kutty = kutty || (function () {
}
}
} else {
triggerEvent(elt, 'responseError.kutty', eventDetail);
triggerErrorEvent(elt, 'responseError.kutty', eventDetail);
}
} catch (e) {
eventDetail['exception'] = e;
triggerEvent(elt, 'onLoadError.kutty', eventDetail);
triggerErrorEvent(elt, 'onLoadError.kutty', eventDetail);
throw e;
} finally {
removeRequestIndicatorClasses(elt);
@ -1135,7 +1222,8 @@ var kutty = kutty || (function () {
}
}
xhr.onerror = function () {
removeRequestIndicatorClasses(elt);triggerEvent(elt, 'sendError.kutty', eventDetail);
removeRequestIndicatorClasses(elt);
triggerErrorEvent(elt, 'sendError.kutty', eventDetail);
endRequestLock();
}
if(!triggerEvent(elt, 'beforeRequest.kutty', eventDetail)) return endRequestLock();
@ -1179,29 +1267,21 @@ var kutty = kutty || (function () {
};
})
function internalEval(str){
return eval(str);
}
function onLoadHelper(callback) {
kutty.on("load.kutty", function(evt) {
callback(evt.detail.elt);
});
}
function logAll(){
kutty.logger = function(elt, event, data) {
if(console) {
console.log(event, elt, data);
}
}
}
// Public API
return {
processElement: processNode,
on: addKuttyEventListener,
onLoad: onLoadHelper,
process: processNode,
on: addKuttyEventListener,
off: removeKuttyEventListener,
trigger : triggerEvent,
find : find,
findAll : findAll,
closest : closest,
remove : removeElement,
addClass : addClassToElement,
removeClass : removeClassFromElement,
toggleClass : toggleClassOnElement,
takeClass : takeClassForElement,
logAll : logAll,
logger : null,
config : {

2
dist/kutty.min.js vendored

File diff suppressed because one or more lines are too long

BIN
dist/kutty.min.js.gz vendored

Binary file not shown.

View File

@ -63,11 +63,6 @@ var kutty = kutty || (function () {
return matchesFunction && matchesFunction.call(elt, selector);
}
function closest(elt, selector) {
do if (elt == null || matches(elt, selector)) return elt;
while (elt = elt && parentElt(elt));
}
function getStartTag(str) {
var tagMatcher = /<([a-z][^\/\0>\x20\t\r\n\f]*)/i
var match = tagMatcher.exec( str );
@ -163,6 +158,119 @@ var kutty = kutty || (function () {
sheet.insertRule(rule, sheet.cssRules.length);
}
//==========================================================================================
// public API
//==========================================================================================
function internalEval(str){
return eval(str);
}
function onLoadHelper(callback) {
kutty.on("load.kutty", function(evt) {
callback(evt.detail.elt);
});
}
function logAll(){
kutty.logger = function(elt, event, data) {
if(console) {
console.log(event, elt, data);
}
}
}
function find(eltOrSelector, selector) {
if (selector) {
eltOrSelector.querySelector(eltOrSelector);
} else {
getDocument().body.querySelector(eltOrSelector);
}
}
function findAll(eltOrSelector, selector) {
if (selector) {
eltOrSelector.querySelectorAll(eltOrSelector);
} else {
getDocument().body.querySelectorAll(eltOrSelector);
}
}
function removeElement(elt, delay) {
if (delay) {
setTimeout(function(){removeElement(elt);}, delay)
} else {
elt.parentElement.removeChild(elt);
}
}
function addClassToElement(elt, clazz, delay) {
if (delay) {
setTimeout(function(){addClassToElement(elt, clazz);}, delay)
} else {
elt.classList.add(clazz);
}
}
function removeClassFromElement(elt, clazz) {
if (delay) {
setTimeout(function(){removeClassFromElement(elt, clazz);}, delay)
} else {
elt.classList.remove(clazz);
}
}
function toggleClassOnElement(elt, clazz) {
elt.classList.toggle(clazz);
}
function takeClassForElement(elt, clazz) {
forEach(elt.parent.children, function(child){
removeClassFromElement(child, clazz);
})
addClassToElement(elt, clazz);
}
function closest(elt, selector) {
do if (elt == null || matches(elt, selector)) return elt;
while (elt = elt && parentElt(elt));
}
function processEventArgs(arg1, arg2, arg3) {
if (isFunction(arg2)) {
return {
target: getDocument().body,
event: arg1,
listener: arg2
}
} else {
return {
target: arg1,
event: arg2,
listener: arg3
}
}
}
function addKuttyEventListener(arg1, arg2, arg3) {
var eventArgs = processEventArgs(arg1, arg2, arg3);
ready(function(){
eventArgs.target.addEventListener(eventArgs.event, eventArgs.listener);
})
return eventArgs.listener;
}
function removeKuttyEventListener(arg1, arg2, arg3) {
var eventArgs = processEventArgs(arg1, arg2, arg3);
ready(function(){
eventArgs.target.addEventListener(eventArgs.event, eventArgs.listener);
})
return eventArgs.listener;
}
//====================================================================
// Node processing
//====================================================================
@ -208,7 +316,7 @@ var kutty = kutty || (function () {
settleTasks = settleTasks.concat(swapOuterHTML(target, fragment));
} else {
child.parentNode.removeChild(child);
triggerEvent(getDocument().body, "oobErrorNoTarget.kutty", {content: child})
triggerErrorEvent(getDocument().body, "oobErrorNoTarget.kutty", {content: child})
}
}
});
@ -535,7 +643,7 @@ var kutty = kutty || (function () {
triggerEvent(elt, "initSSE.kutty", detail);
var source = new EventSource(sseSrc, detail.config);
source.onerror = function (e) {
triggerEvent(elt, "sseError.kutty", {error:e, source:source});
triggerErrorEvent(elt, "sseError.kutty", {error:e, source:source});
maybeCloseSSESource(elt);
};
getInternalData(elt).sseSource = source;
@ -557,7 +665,7 @@ var kutty = kutty || (function () {
};
sseSource.sseSource.addEventListener(sseEventName, sseListener);
} else {
triggerEvent(elt, "noSSESourceError.kutty")
triggerErrorEvent(elt, "noSSESourceError.kutty")
}
}
@ -651,57 +759,21 @@ var kutty = kutty || (function () {
return evt;
}
function triggerErrorEvent(elt, eventName, detail) {
triggerEvent(elt, eventName, Object.assign({isError:true}, details));
}
function triggerEvent(elt, eventName, detail) {
detail["elt"] = elt;
var event = makeEvent(eventName, detail);
if (kutty.logger) {
kutty.logger(elt, eventName, detail);
if (eventName.indexOf("Error") > 0) {
if (detail.isError) {
sendError(elt, eventName, detail);
}
}
var eventResult = elt.dispatchEvent(event);
var allResult = elt.dispatchEvent(makeEvent("all.kutty", {originalDetail:detail, originalEvent: event}));
return eventResult && allResult;
}
function processEventArgs(arg1, arg2, arg3) {
if (isFunction(arg1)) {
return {
target: getDocument().body,
event: "all.kutty",
listener: arg1
}
} else if (isFunction(arg2)) {
return {
target: getDocument().body,
event: arg1,
listener: arg2
}
} else {
return {
target: arg1,
event: arg2,
listener: arg3
}
}
}
function addKuttyEventListener(arg1, arg2, arg3) {
var eventArgs = processEventArgs(arg1, arg2, arg3);
ready(function(){
eventArgs.target.addEventListener(eventArgs.event, eventArgs.listener);
})
return eventArgs.listener;
}
function removeKuttyEventListener(arg1, arg2, arg3) {
var eventArgs = processEventArgs(arg1, arg2, arg3);
ready(function(){
eventArgs.target.addEventListener(eventArgs.event, eventArgs.listener);
})
return eventArgs.listener;
return eventResult;
}
//====================================================================
@ -771,7 +843,7 @@ var kutty = kutty || (function () {
settleImmediately(swapInnerHTML(getHistoryElement(), fragment));
currentPathForHistory = path;
} else {
triggerEvent(getDocument().body, "historyCacheMissLoadError.kutty", details);
triggerErrorEvent(getDocument().body, "historyCacheMissLoadError.kutty", details);
}
};
request.send();
@ -1007,7 +1079,7 @@ var kutty = kutty || (function () {
function issueAjaxRequest(elt, verb, path, eventTarget) {
var target = getTarget(elt);
if (target == null) {
triggerEvent(elt, 'targetError.kutty', {target: getRawAttribute(elt, "kt-target")});
triggerErrorEvent(elt, 'targetError.kutty', {target: getRawAttribute(elt, "kt-target")});
return;
}
var eltData = getInternalData(elt);
@ -1125,7 +1197,7 @@ var kutty = kutty || (function () {
doSettle();
}
} catch (e) {
triggerEvent(elt, 'swapError.kutty', eventDetail);
triggerErrorEvent(elt, 'swapError.kutty', eventDetail);
throw e;
}
};
@ -1137,11 +1209,11 @@ var kutty = kutty || (function () {
}
}
} else {
triggerEvent(elt, 'responseError.kutty', eventDetail);
triggerErrorEvent(elt, 'responseError.kutty', eventDetail);
}
} catch (e) {
eventDetail['exception'] = e;
triggerEvent(elt, 'onLoadError.kutty', eventDetail);
triggerErrorEvent(elt, 'onLoadError.kutty', eventDetail);
throw e;
} finally {
removeRequestIndicatorClasses(elt);
@ -1150,7 +1222,8 @@ var kutty = kutty || (function () {
}
}
xhr.onerror = function () {
removeRequestIndicatorClasses(elt);triggerEvent(elt, 'sendError.kutty', eventDetail);
removeRequestIndicatorClasses(elt);
triggerErrorEvent(elt, 'sendError.kutty', eventDetail);
endRequestLock();
}
if(!triggerEvent(elt, 'beforeRequest.kutty', eventDetail)) return endRequestLock();
@ -1194,30 +1267,21 @@ var kutty = kutty || (function () {
};
})
function internalEval(str){
return eval(str);
}
function onLoadHelper(callback) {
kutty.on("load.kutty", function(evt) {
callback(evt.detail.elt);
});
}
function logAll(){
kutty.logger = function(elt, event, data) {
if(console) {
console.log(event, elt, data);
}
}
}
// Public API
return {
onLoad: onLoadHelper,
process: processNode,
on: addKuttyEventListener,
off: removeKuttyEventListener,
onLoad: onLoadHelper,
trigger : triggerEvent,
find : find,
findAll : findAll,
closest : closest,
remove : removeElement,
addClass : addClassToElement,
removeClass : removeClassFromElement,
toggleClass : toggleClassOnElement,
takeClass : takeClassForElement,
logAll : logAll,
logger : null,
config : {

View File

@ -45,6 +45,9 @@
<div class="1 col">
<a href="/examples">examples</a>
</div>
<div class="1 col">
<a href="/talk">talk</a>
</div>
<div class="6 col"></div>
<div class="1 col">
<a href="https://github.com/bigskysoftware/kutty">github</a>

View File

@ -15,7 +15,7 @@ Kutty is a set of extensions (attributes, request headers, etc.) that help you b
[advanced UX](/examples) with the [simplicity](https://en.wikipedia.org/wiki/HATEOAS) and
[power](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm) of HTML.
Kutty is small ([~5Kb min.gz'd](https://unpkg.com/kutty.org/dist/)), [dependency-free](https://github.com/bigskysoftware/kutty/blob/master/package.json)
Kutty is small ([~6k min.gz'd](https://unpkg.com/kutty.org/dist/)), [dependency-free](https://github.com/bigskysoftware/kutty/blob/master/package.json)
& you can try it out quickly, without a huge rewrite.
## Quick Start

View File

@ -0,0 +1,40 @@
---
layout: layout.njk
title: </> kutty - high power tools for html
---
## Kutty 0.0.1 Release
I'm pleased to announce the [first release](https://unpkg.com/browse/kutty.org@0.0.1/) of kutty, the successor
to [intercooler.js](http://intercoolerjs.org)!
Like intercooler, kutty brings the power of modern browsers into HTML.
#### What's new/different about kutty vs. intercooler?
* First and foremost, kutty has no external dependencies! No more dragging jQuery in if you don't want it.
* I've tried to follow conventional naming and behavior standards more closely where applicable (e.g. [`innerHTML`](/attributes/kt-swap) and [`outerHTML`](/attributes/kt-swap))
* Kutty is less kitchen-sink-of-features and more pluggable than intercooler
* Kutty has a better swapping mechanism which introduces a settling step, which allows for nice CSS transitions
without plain old HTML
Beyond that, basic kutty and intercooler code will look a lot a like:
```html
<div kt-post="/clicked">Click Me!</div>
```
This will issue an AJAX post to `/clicked`, in a manner familiar to anyone who has used intercooler.
#### What will happen to intercooler?
I'm planning on maintaining both projects. Intercooler is a slow moving project anyway, and the code is stable and
works fine for people who want to go the jQuery route. I have a large application written with it and I'm not planning
on moving that to kutty any time soon.
#### How hard will a port to kutty from intercooler be?
Depends a lot on how into the weeds you got with intercooler. The core attributes are pretty close to one another
but if you were using `ic-action` or event handlers extensively it will be a project. That's why I chose to rename it,
and to continue to maintain intercooler.

17
www/talk.md Normal file
View File

@ -0,0 +1,17 @@
---
layout: layout.njk
title: </> kutty - high power tools for html
---
## Talk Kutty
Right now the best place to talk about kutty is the [intercooler gitter room](https://gitter.im/intercooler-js/Lobby)
I'll be setting up a forum and
## Announcements
I'm trying to set up a blog [here](/posts)