diff --git a/dist/kutty.js b/dist/kutty.js index b0b03e30..6a263698 100644 --- a/dist/kutty.js +++ b/dist/kutty.js @@ -642,7 +642,7 @@ var kutty = kutty || (function () { // History Support //==================================================================== function getHistoryElement() { - var historyElt = getDocument().querySelector('.kt-history-elt'); + var historyElt = getDocument().querySelector('.kutty-history-elt'); return historyElt || getDocument().body; } @@ -697,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-elt') || fragment; + fragment = fragment.querySelector('.kutty-history-elt') || fragment; settleImmediately(swapInnerHTML(getHistoryElement(), fragment)); } }; @@ -736,7 +736,7 @@ var kutty = kutty || (function () { indicators = [elt]; } forEach(indicators, function(ic) { - ic.classList[action].call(ic.classList, "kutty-show-indicator"); + ic.classList[action].call(ic.classList, "kutty-request"); }); } @@ -1055,6 +1055,12 @@ var kutty = kutty || (function () { } } + // insert kutty-indicator css rules + var sheet = getDocument().styleSheets[0]; + sheet.insertRule(".kutty-indicator{opacity:0;transition: opacity 500ms ease-in;}\n" + + ".kutty-request .kutty-indicator{opacity:1}\n" + + ".kutty-request.kutty-indicator{opacity:1}\n", sheet.cssRules.length); + // initialize the document ready(function () { var body = getDocument().body; diff --git a/dist/kutty.min.js b/dist/kutty.min.js index e73235d8..ba9edb44 100644 --- a/dist/kutty.min.js +++ b/dist/kutty.min.js @@ -1 +1 @@ -var kutty=kutty||function(){"use strict";var e=["get","post","put","delete","patch"];function g(e){if(e==="null"||e==="false"||e===""){return null}else if(e.lastIndexOf("ms")===e.length-2){return parseFloat(e.substr(0,e.length-2))}else if(e.lastIndexOf("s")===e.length-1){return parseFloat(e.substr(0,e.length-1))*1e3}else{return parseFloat(e)}}function u(e,t){return e.getAttribute&&e.getAttribute(t)}function o(e,t){return u(e,t)||u(e,"data-"+t)}function a(e){return e.parentElement}function s(){return document}function l(e,t){if(t(e)){return e}else if(a(e)){return l(a(e),t)}else{return null}}function h(e,t){var r=null;l(e,function(e){return r=u(e,t)});return r}function f(e,t){return e!=null&&(e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.oMatchesSelector).call(e,t)}function c(e,t){do{if(e==null||f(e,t))return e}while(e=e&&a(e))}function v(e){var t=new DOMParser;var r=t.parseFromString(e,"text/html");return r.body}function t(e,t){return Object.prototype.toString.call(e)==="[object "+t+"]"}function d(e){return t(e,"Function")}function p(e){return t(e,"Object")}function y(e){var t="kutty-internal-data";var r=e[t];if(!r){r=e[t]={}}return r}function m(e,t){if(e){for(var r=0;r=0}function k(e){return s().body.contains(e)}function b(e,t){return e.concat(t)}function w(e){return e.split(/\s+/)}function S(e){var t=l(e,function(e){return u(e,"kt-target")!==null});if(t){var r=u(t,"kt-target");if(r==="this"){return t}else{return s().querySelector(r)}}else{var n=y(e);if(n.boosted){return s().body}else{return e}}}function E(t,r){m(t.attributes,function(e){if(!r.hasAttribute(e.name)){t.removeAttribute(e.name)}});m(r.attributes,function(e){t.setAttribute(e.name,e.value)})}function O(e){var n=[];m(e.children,function(e){if(o(e,"kt-swap-oob")==="true"){var t=s().getElementById(e.id);if(t){var r=s().createDocumentFragment();r.appendChild(e);n=n.concat(T(t,r))}else{e.parentNode.removeChild(e);$(s().body,"oobErrorNoTarget.kutty",{id:e.id,content:e})}}});return n}function L(n,e){var i=[];m(e.querySelectorAll("[id]"),function(e){var t=n.querySelector(e.tagName+"[id="+e.id+"]");if(t){var r=e.cloneNode();E(e,t);i.push(function(){E(e,r)})}});return i}function i(e,t,r){var n=L(e,r);while(r.childNodes.length>0){var i=r.firstChild;e.insertBefore(i,t);if(i.nodeType!==Node.TEXT_NODE){$(i,"load.kutty",{elt:i,parent:a(i)});Y(i)}}return n}function T(e,t){if(e.tagName==="BODY"){return q(e,t)}else{var r=i(a(e),e,t);a(e).removeChild(e);return r}}function C(e,t){return i(e,e.firstChild,t)}function x(e,t){return i(a(e),e,t)}function A(e,t){return i(e,null,t)}function N(e,t){return i(a(e),e.nextSibling,t)}function q(e,t){var r=e.firstChild;var n=i(e,r,t);if(r){while(r.nextSibling){e.removeChild(r.nextSibling)}e.removeChild(r)}return n}function I(e,t){var r=h(e,"kt-select");if(r){var n=s().createDocumentFragment();m(t.querySelectorAll(r),function(e){n.appendChild(e)});t=n}return t}function M(e,t,r,n){var i=v(n);if(i){var a=O(i);i=I(r,i);switch(e){case"outerHTML":return b(a,T(t,i));case"afterbegin":return b(a,C(t,i));case"beforebegin":return b(a,x(t,i));case"beforeend":return b(a,A(t,i));case"afterend":return b(a,N(t,i));default:return b(a,q(t,i))}}}function D(e,t){if(t){if(t.indexOf("{")===0){var r=JSON.parse(t);for(var n in r){if(r.hasOwnProperty(n)){var i=r[n];if(!p(i)){i={value:i}}$(e,n,i)}}}else{$(e,t,[])}}}function R(e){var t={trigger:"click"};var r=h(e,"kt-trigger");if(r){var n=w(r);if(n.length>0){var i=n[0];if(i==="every"){t.pollInterval=g(n[1])}else if(i.indexOf("sse:")===0){t.sseEvent=i.substr(4)}else{t["trigger"]=i;for(var a=1;a1){var r=t[0];var n=t[1].trim();var i;var a;if(n.indexOf(":")>0){var o=n.split(":");i=o[0];a=g(o[1])}else{i=n;a=100}return{operation:r,cssClass:i,delay:a}}else{return null}}function H(i,e,t){m(e.split("&"),function(e){var n=0;m(e.split(","),function(e){var t=e.trim();var r=F(t);if(r){if(r.operation==="toggle"){setTimeout(function(){setInterval(function(){i.classList[r.operation].call(i.classList,r.cssClass)},r.delay)},n);n=n+r.delay}else{n=n+r.delay;setTimeout(function(){i.classList[r.operation].call(i.classList,r.cssClass)},n)}}})})}function P(e,t,r,n){var i=y(e);i.timeout=setTimeout(function(){if(k(e)){we(e,t,r);P(e,t,o(e,"kt-"+t),n)}},n)}function X(e){return location.hostname===e.hostname&&u(e,"href")&&!u(e,"href").startsWith("#")}function U(e,t,r){if(e.tagName==="A"&&X(e)||e.tagName==="FORM"){t.boosted=true;var n,i;if(e.tagName==="A"){n="get";i=u(e,"href")}else{var a=u(e,"method");n=a?a.toLowerCase():"get";i=u(e,"action")}B(e,n,i,t,r,true)}}function j(e){return e.tagName==="FORM"||f(e,'input[type="submit"], button')&&c(e,"form")!==null||e.tagName==="A"&&e.href&&e.href.indexOf("#")!==0}function B(i,a,o,e,u,s){var t=function(e){if(s||j(i))e.preventDefault();var t=y(e);var r=y(i);if(!t.handled){t.handled=true;if(u.once){if(r.triggeredOnce){return}else{r.triggeredOnce=true}}if(u.changed){if(r.lastValue===i.value){return}else{r.lastValue=i.value}}if(r.delayed){clearTimeout(r.delayed)}var n=function(){we(i,a,o,e.target)};if(u.delay){r.delayed=setTimeout(n,g(u.delay))}else{n()}}};e.trigger=u.trigger;e.eventListener=t;i.addEventListener(u.trigger,t)}function J(){if(!window["kuttyScrollHandler"]){var e=function(){m(s().querySelectorAll("[kt-trigger='reveal']"),function(e){z(e)})};window["kuttyScrollHandler"]=e;window.addEventListener("scroll",e)}}function z(e){var t=y(e);if(!t.revealed&&r(e)){t.revealed=true;we(e,t.verb,t.path)}}function K(e){if(!k(e)){e.sseSource.close();return true}}function V(t,e){var r={initializer:function(){new EventSource(e,r.config)},config:{withCredentials:true}};$(t,"initSSE.kutty",{config:r});var n=r.initializer();n.onerror=function(e){$(t,"sseError.kutty",{error:e,source:n});K(t)};y(t).sseSource=n}function G(e,t,r,n){var i=l(t,function(e){return e.sseSource});if(i){var a=function(){if(!K(i)){if(k(t)){we(t,r,n)}else{i.sseSource.removeEventListener(e,a)}}};i.sseSource.addEventListener(e,a)}else{$(t,"noSSESourceError.kutty")}}function _(e,t,r,n){if(!e.loaded){e.loaded=true;we(t,r,n)}}function W(r,n,i){var a=false;m(e,function(e){var t=o(r,"kt-"+e);if(t){a=true;n.path=t;n.verb=e;if(i.sseEvent){G(i.sseEvent,r,e,t)}else if(i.trigger==="revealed"){J();z(r)}else if(i.trigger==="load"){_(n,r,e,t)}else if(i.pollInterval){n.polling=true;P(r,e,t,i.pollInterval)}else{B(r,e,t,n,i)}}});return a}function Y(e){var t=y(e);if(!t.processed){t.processed=true;var r=R(e);var n=W(e,t,r);if(!n&&h(e,"kt-boost")==="true"){U(e,t,r)}var i=o(e,"kt-sse-source");if(i){V(e,i)}var a=o(e,"kt-classes");if(a){H(e,a)}}if(e.children){m(e.children,function(e){Y(e)})}}function Q(e,t,r){var n=h(e,"kt-error-url");if(n){var i=new XMLHttpRequest;i.open("POST",n);i.setRequestHeader("Content-Type","application/json;charset=UTF-8");i.send(JSON.stringify({elt:e.id,event:t,detail:r}))}}function Z(e,t){var r;if(window.CustomEvent&&typeof window.CustomEvent==="function"){r=new CustomEvent(e,{bubbles:true,cancelable:true,detail:t})}else{r=s().createEvent("CustomEvent");r.initCustomEvent(e,true,true,t)}return r}function $(e,t,r){r["elt"]=e;var n=Z(t,r);if(kutty.logger){kutty.logger(e,t,r);if(t.indexOf("Error")>0){Q(e,t,r)}}var i=e.dispatchEvent(n);var a=e.dispatchEvent(Z("all.kutty",{elt:e,originalDetail:r,originalEvent:n}));return i&&a}function n(e,t,r){var n,i,a;if(d(e)){Se(function(){n=s().body;i="all.kutty";a=e;n.addEventListener(i,a)})}else if(d(t)){Se(function(){n=s().body;i=e;a=t;n.addEventListener(i,a)})}else{n=e;i=t;a=r;n.addEventListener(i,a)}}function ee(){var e=s().querySelector(".kt-history-elt");return e||s().body}function te(e,r){e=e.sort(function(e,t){return r[t]-r[e]});var t=0;m(e,function(e){t++;if(t>20){delete r[e];localStorage.removeItem(e)}})}function re(e){var t=JSON.parse(localStorage.getItem("kt-history-timestamps"))||{};t[e]=Date.now();var r=Object.keys(t);if(r.length>20){te(r,t)}localStorage.setItem("kt-history-timestamps",JSON.stringify(t))}function ne(){var e=ee();var t=location.pathname+location.search;$(s().body,"historyUpdate.kutty",{path:t,historyElement:e});history.replaceState({},s().title,window.location.href);localStorage.setItem("kt-history:"+t,e.innerHTML);re(t)}function ie(e){history.pushState({},"",e)}function ae(e){m(e,function(e){e.call()})}function oe(t){$(s().body,"historyCacheMiss.kutty",{path:t});var e=new XMLHttpRequest;e.open("GET",t,true);e.onload=function(){$(s().body,"historyCacheMissLoad.kutty",{path:t});if(this.status>=200&&this.status<400){var e=v(this.response);e=e.querySelector(".kt-history-elt")||e;ae(q(ee(),e))}}}function ue(){var e=location.pathname+location.search;$(s().body,"historyRestore.kutty",{path:e});var t=localStorage.getItem("kt-history:"+e);if(t){re(e);ae(q(ee(),v(t)))}else{oe(e)}}function se(e){return h(e,"kt-push-url")==="true"||e.tagName==="A"&&y(e).boosted}function le(e){ce(e,"add")}function fe(e){ce(e,"remove")}function ce(e,t){var r=h(e,"kt-indicator");if(r){var n=s().querySelectorAll(r)}else{n=[e]}m(n,function(e){e.classList[t].call(e.classList,"kutty-show-indicator")})}function ve(e,t){for(var r=0;r0){r["swapStyle"]=n[0];for(var i=1;i=200&&this.status<400){if(this.status!==204){var i=this.response;if(!$(o,"beforeSwap.kutty",{xhr:f,target:s,response:i}))return;if(n){ne()}var a=be(o);s.classList.add("kutty-swapping");var e=function(){try{var e=M(a.swapStyle,s,o,i);s.classList.remove("kutty-swapping");s.classList.add("kutty-settling");$(o,"afterSwap.kutty",{xhr:f,target:s});var t=function(){m(e,function(e){e.call()});s.classList.remove("kutty-settling");if(n){ie(r||v);ne()}$(o,"afterSettle.kutty",{xhr:f,target:s})};if(a.settleDelay>0){setTimeout(t,a.settleDelay)}else{t()}}catch(e){$(o,"swapError.kutty",{xhr:f,response:f.response,status:f.status,target:s});throw e}};if(a.swapDelay>0){setTimeout(e,g(a.swapDelay))}else{e()}}}else{$(o,"responseError.kutty",{xhr:f,response:f.response,status:f.status,target:s})}}catch(e){$(o,"onLoadError.kutty",{xhr:f,response:f.response,status:f.status,target:s});throw e}finally{fe(o);u();$(o,"afterOnLoad.kutty",{xhr:f,response:f.response,status:f.status,target:s})}};f.onerror=function(){fe(o);$(o,"sendError.kutty",{xhr:f});u()};if(!$(o,"beforeRequest.kutty",{xhr:f,values:c,target:s}))return u();le(o);f.send(e==="get"?null:pe(c))}function Se(e){if(s().readyState!=="loading"){e()}else{s().addEventListener("DOMContentLoaded",e)}}Se(function(){var e=s().body;Y(e);$(e,"load.kutty",{elt:e});window.onpopstate=function(){ue()}});function Ee(e){return eval(e)}function Oe(t){kutty.on("load.kutty",function(e){t(e.detail.elt)})}return{processElement:Y,on:n,onLoad:Oe,version:"0.0.1",_:Ee}}(); \ No newline at end of file +var kutty=kutty||function(){"use strict";var t=["get","post","put","delete","patch"];function y(t){if(t==="null"||t==="false"||t===""){return null}else if(t.lastIndexOf("ms")===t.length-2){return parseFloat(t.substr(0,t.length-2))}else if(t.lastIndexOf("s")===t.length-1){return parseFloat(t.substr(0,t.length-1))*1e3}else{return parseFloat(t)}}function u(t,e){return t.getAttribute&&t.getAttribute(e)}function o(t,e){return u(t,e)||u(t,"data-"+e)}function a(t){return t.parentElement}function s(){return document}function l(t,e){if(e(t)){return t}else if(a(t)){return l(a(t),e)}else{return null}}function g(t,e){var r=null;l(t,function(t){return r=u(t,e)});return r}function f(t,e){return t!=null&&(t.matches||t.matchesSelector||t.msMatchesSelector||t.mozMatchesSelector||t.webkitMatchesSelector||t.oMatchesSelector).call(t,e)}function c(t,e){do{if(t==null||f(t,e))return t}while(t=t&&a(t))}function v(t){var e=new DOMParser;var r=e.parseFromString(t,"text/html");return r.body}function e(t,e){return Object.prototype.toString.call(t)==="[object "+e+"]"}function d(t){return e(t,"Function")}function h(t){return e(t,"Object")}function p(t){var e="kutty-internal-data";var r=t[e];if(!r){r=t[e]={}}return r}function m(t,e){if(t){for(var r=0;r=0}function k(t){return s().body.contains(t)}function b(t,e){return t.concat(e)}function S(t){return t.split(/\s+/)}function w(t){var e=l(t,function(t){return u(t,"kt-target")!==null});if(e){var r=u(e,"kt-target");if(r==="this"){return e}else{return s().querySelector(r)}}else{var n=p(t);if(n.boosted){return s().body}else{return t}}}function E(e,r){m(e.attributes,function(t){if(!r.hasAttribute(t.name)){e.removeAttribute(t.name)}});m(r.attributes,function(t){e.setAttribute(t.name,t.value)})}function O(t){var n=[];m(t.children,function(t){if(o(t,"kt-swap-oob")==="true"){var e=s().getElementById(t.id);if(e){var r=s().createDocumentFragment();r.appendChild(t);n=n.concat(T(e,r))}else{t.parentNode.removeChild(t);$(s().body,"oobErrorNoTarget.kutty",{id:t.id,content:t})}}});return n}function L(n,t){var i=[];m(t.querySelectorAll("[id]"),function(t){var e=n.querySelector(t.tagName+"[id="+t.id+"]");if(e){var r=t.cloneNode();E(t,e);i.push(function(){E(t,r)})}});return i}function i(t,e,r){var n=L(t,r);while(r.childNodes.length>0){var i=r.firstChild;t.insertBefore(i,e);if(i.nodeType!==Node.TEXT_NODE){$(i,"load.kutty",{elt:i,parent:a(i)});Y(i)}}return n}function T(t,e){if(t.tagName==="BODY"){return N(t,e)}else{var r=i(a(t),t,e);a(t).removeChild(t);return r}}function C(t,e){return i(t,t.firstChild,e)}function x(t,e){return i(a(t),t,e)}function q(t,e){return i(t,null,e)}function A(t,e){return i(a(t),t.nextSibling,e)}function N(t,e){var r=t.firstChild;var n=i(t,r,e);if(r){while(r.nextSibling){t.removeChild(r.nextSibling)}t.removeChild(r)}return n}function I(t,e){var r=g(t,"kt-select");if(r){var n=s().createDocumentFragment();m(e.querySelectorAll(r),function(t){n.appendChild(t)});e=n}return e}function M(t,e,r,n){var i=v(n);if(i){var a=O(i);i=I(r,i);switch(t){case"outerHTML":return b(a,T(e,i));case"afterbegin":return b(a,C(e,i));case"beforebegin":return b(a,x(e,i));case"beforeend":return b(a,q(e,i));case"afterend":return b(a,A(e,i));default:return b(a,N(e,i))}}}function R(t,e){if(e){if(e.indexOf("{")===0){var r=JSON.parse(e);for(var n in r){if(r.hasOwnProperty(n)){var i=r[n];if(!h(i)){i={value:i}}$(t,n,i)}}}else{$(t,e,[])}}}function D(t){var e={trigger:"click"};var r=g(t,"kt-trigger");if(r){var n=S(r);if(n.length>0){var i=n[0];if(i==="every"){e.pollInterval=y(n[1])}else if(i.indexOf("sse:")===0){e.sseEvent=i.substr(4)}else{e["trigger"]=i;for(var a=1;a1){var r=e[0];var n=e[1].trim();var i;var a;if(n.indexOf(":")>0){var o=n.split(":");i=o[0];a=y(o[1])}else{i=n;a=100}return{operation:r,cssClass:i,delay:a}}else{return null}}function H(i,t,e){m(t.split("&"),function(t){var n=0;m(t.split(","),function(t){var e=t.trim();var r=F(e);if(r){if(r.operation==="toggle"){setTimeout(function(){setInterval(function(){i.classList[r.operation].call(i.classList,r.cssClass)},r.delay)},n);n=n+r.delay}else{n=n+r.delay;setTimeout(function(){i.classList[r.operation].call(i.classList,r.cssClass)},n)}}})})}function P(t,e,r,n){var i=p(t);i.timeout=setTimeout(function(){if(k(t)){St(t,e,r);P(t,e,o(t,"kt-"+e),n)}},n)}function X(t){return location.hostname===t.hostname&&u(t,"href")&&!u(t,"href").startsWith("#")}function U(t,e,r){if(t.tagName==="A"&&X(t)||t.tagName==="FORM"){e.boosted=true;var n,i;if(t.tagName==="A"){n="get";i=u(t,"href")}else{var a=u(t,"method");n=a?a.toLowerCase():"get";i=u(t,"action")}B(t,n,i,e,r,true)}}function j(t){return t.tagName==="FORM"||f(t,'input[type="submit"], button')&&c(t,"form")!==null||t.tagName==="A"&&t.href&&t.href.indexOf("#")!==0}function B(i,a,o,t,u,s){var e=function(t){if(s||j(i))t.preventDefault();var e=p(t);var r=p(i);if(!e.handled){e.handled=true;if(u.once){if(r.triggeredOnce){return}else{r.triggeredOnce=true}}if(u.changed){if(r.lastValue===i.value){return}else{r.lastValue=i.value}}if(r.delayed){clearTimeout(r.delayed)}var n=function(){St(i,a,o,t.target)};if(u.delay){r.delayed=setTimeout(n,y(u.delay))}else{n()}}};t.trigger=u.trigger;t.eventListener=e;i.addEventListener(u.trigger,e)}function J(){if(!window["kuttyScrollHandler"]){var t=function(){m(s().querySelectorAll("[kt-trigger='reveal']"),function(t){z(t)})};window["kuttyScrollHandler"]=t;window.addEventListener("scroll",t)}}function z(t){var e=p(t);if(!e.revealed&&r(t)){e.revealed=true;St(t,e.verb,e.path)}}function K(t){if(!k(t)){t.sseSource.close();return true}}function V(e,t){var r={initializer:function(){new EventSource(t,r.config)},config:{withCredentials:true}};$(e,"initSSE.kutty",{config:r});var n=r.initializer();n.onerror=function(t){$(e,"sseError.kutty",{error:t,source:n});K(e)};p(e).sseSource=n}function G(t,e,r,n){var i=l(e,function(t){return t.sseSource});if(i){var a=function(){if(!K(i)){if(k(e)){St(e,r,n)}else{i.sseSource.removeEventListener(t,a)}}};i.sseSource.addEventListener(t,a)}else{$(e,"noSSESourceError.kutty")}}function _(t,e,r,n){if(!t.loaded){t.loaded=true;St(e,r,n)}}function W(r,n,i){var a=false;m(t,function(t){var e=o(r,"kt-"+t);if(e){a=true;n.path=e;n.verb=t;if(i.sseEvent){G(i.sseEvent,r,t,e)}else if(i.trigger==="revealed"){J();z(r)}else if(i.trigger==="load"){_(n,r,t,e)}else if(i.pollInterval){n.polling=true;P(r,t,e,i.pollInterval)}else{B(r,t,e,n,i)}}});return a}function Y(t){var e=p(t);if(!e.processed){e.processed=true;var r=D(t);var n=W(t,e,r);if(!n&&g(t,"kt-boost")==="true"){U(t,e,r)}var i=o(t,"kt-sse-source");if(i){V(t,i)}var a=o(t,"kt-classes");if(a){H(t,a)}}if(t.children){m(t.children,function(t){Y(t)})}}function Q(t,e,r){var n=g(t,"kt-error-url");if(n){var i=new XMLHttpRequest;i.open("POST",n);i.setRequestHeader("Content-Type","application/json;charset=UTF-8");i.send(JSON.stringify({elt:t.id,event:e,detail:r}))}}function Z(t,e){var r;if(window.CustomEvent&&typeof window.CustomEvent==="function"){r=new CustomEvent(t,{bubbles:true,cancelable:true,detail:e})}else{r=s().createEvent("CustomEvent");r.initCustomEvent(t,true,true,e)}return r}function $(t,e,r){r["elt"]=t;var n=Z(e,r);if(kutty.logger){kutty.logger(t,e,r);if(e.indexOf("Error")>0){Q(t,e,r)}}var i=t.dispatchEvent(n);var a=t.dispatchEvent(Z("all.kutty",{elt:t,originalDetail:r,originalEvent:n}));return i&&a}function n(t,e,r){var n,i,a;if(d(t)){wt(function(){n=s().body;i="all.kutty";a=t;n.addEventListener(i,a)})}else if(d(e)){wt(function(){n=s().body;i=t;a=e;n.addEventListener(i,a)})}else{n=t;i=e;a=r;n.addEventListener(i,a)}}function tt(){var t=s().querySelector(".kutty-history-elt");return t||s().body}function et(t,r){t=t.sort(function(t,e){return r[e]-r[t]});var e=0;m(t,function(t){e++;if(e>20){delete r[t];localStorage.removeItem(t)}})}function rt(t){var e=JSON.parse(localStorage.getItem("kt-history-timestamps"))||{};e[t]=Date.now();var r=Object.keys(e);if(r.length>20){et(r,e)}localStorage.setItem("kt-history-timestamps",JSON.stringify(e))}function nt(){var t=tt();var e=location.pathname+location.search;$(s().body,"historyUpdate.kutty",{path:e,historyElement:t});history.replaceState({},s().title,window.location.href);localStorage.setItem("kt-history:"+e,t.innerHTML);rt(e)}function it(t){history.pushState({},"",t)}function at(t){m(t,function(t){t.call()})}function ot(e){$(s().body,"historyCacheMiss.kutty",{path:e});var t=new XMLHttpRequest;t.open("GET",e,true);t.onload=function(){$(s().body,"historyCacheMissLoad.kutty",{path:e});if(this.status>=200&&this.status<400){var t=v(this.response);t=t.querySelector(".kutty-history-elt")||t;at(N(tt(),t))}}}function ut(){var t=location.pathname+location.search;$(s().body,"historyRestore.kutty",{path:t});var e=localStorage.getItem("kt-history:"+t);if(e){rt(t);at(N(tt(),v(e)))}else{ot(t)}}function st(t){return g(t,"kt-push-url")==="true"||t.tagName==="A"&&p(t).boosted}function lt(t){ct(t,"add")}function ft(t){ct(t,"remove")}function ct(t,e){var r=g(t,"kt-indicator");if(r){var n=s().querySelectorAll(r)}else{n=[t]}m(n,function(t){t.classList[e].call(t.classList,"kutty-request")})}function vt(t,e){for(var r=0;r0){r["swapStyle"]=n[0];for(var i=1;i=200&&this.status<400){if(this.status!==204){var i=this.response;if(!$(o,"beforeSwap.kutty",{xhr:f,target:s,response:i}))return;if(n){nt()}var a=bt(o);s.classList.add("kutty-swapping");var t=function(){try{var t=M(a.swapStyle,s,o,i);s.classList.remove("kutty-swapping");s.classList.add("kutty-settling");$(o,"afterSwap.kutty",{xhr:f,target:s});var e=function(){m(t,function(t){t.call()});s.classList.remove("kutty-settling");if(n){it(r||v);nt()}$(o,"afterSettle.kutty",{xhr:f,target:s})};if(a.settleDelay>0){setTimeout(e,a.settleDelay)}else{e()}}catch(t){$(o,"swapError.kutty",{xhr:f,response:f.response,status:f.status,target:s});throw t}};if(a.swapDelay>0){setTimeout(t,y(a.swapDelay))}else{t()}}}else{$(o,"responseError.kutty",{xhr:f,response:f.response,status:f.status,target:s})}}catch(t){$(o,"onLoadError.kutty",{xhr:f,response:f.response,status:f.status,target:s});throw t}finally{ft(o);u();$(o,"afterOnLoad.kutty",{xhr:f,response:f.response,status:f.status,target:s})}};f.onerror=function(){ft(o);$(o,"sendError.kutty",{xhr:f});u()};if(!$(o,"beforeRequest.kutty",{xhr:f,values:c,target:s}))return u();lt(o);f.send(t==="get"?null:ht(c))}function wt(t){if(s().readyState!=="loading"){t()}else{s().addEventListener("DOMContentLoaded",t)}}var Et=s().styleSheets[0];Et.insertRule(".kutty-indicator{opacity:0;transition: opacity 500ms ease-in;}\n"+".kutty-request .kutty-indicator{opacity:1}\n"+".kutty-request.kutty-indicator{opacity:1}\n",Et.cssRules.length);wt(function(){var t=s().body;Y(t);$(t,"load.kutty",{elt:t});window.onpopstate=function(){ut()}});function Ot(t){return eval(t)}function Lt(e){kutty.on("load.kutty",function(t){e(t.detail.elt)})}return{processElement:Y,on:n,onLoad:Lt,version:"0.0.1",_:Ot}}(); \ No newline at end of file diff --git a/dist/kutty.min.js.gz b/dist/kutty.min.js.gz index 134355a1..07de18ab 100644 Binary files a/dist/kutty.min.js.gz and b/dist/kutty.min.js.gz differ diff --git a/src/kutty.js b/src/kutty.js index 9d594853..6d671843 100644 --- a/src/kutty.js +++ b/src/kutty.js @@ -122,6 +122,11 @@ var kutty = kutty || (function () { return trigger.split(/\s+/); } + function addRule(rule) { + var sheet = getDocument().styleSheets[0]; + sheet.insertRule(rule, sheet.cssRules.length); + } + //==================================================================== // Node processing //==================================================================== @@ -642,7 +647,7 @@ var kutty = kutty || (function () { // History Support //==================================================================== function getHistoryElement() { - var historyElt = getDocument().querySelector('.kt-history-elt'); + var historyElt = getDocument().querySelector('.kutty-history-elt'); return historyElt || getDocument().body; } @@ -697,7 +702,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-elt') || fragment; + fragment = fragment.querySelector('.kutty-history-elt') || fragment; settleImmediately(swapInnerHTML(getHistoryElement(), fragment)); } }; @@ -1055,6 +1060,11 @@ var kutty = kutty || (function () { } } + // insert kutty-indicator css rules + addRule(".kutty-indicator{opacity:0;transition: opacity 200ms ease-in;}"); + addRule(".kutty-request .kutty-indicator{opacity:1}"); + addRule(".kutty-request.kutty-indicator{opacity:1}"); + // initialize the document ready(function () { var body = getDocument().body; diff --git a/test/browser-only.html b/test/browser-only.html index 21add4ed..7b4a6be4 100644 --- a/test/browser-only.html +++ b/test/browser-only.html @@ -27,7 +27,7 @@ Work Area
-
+
diff --git a/test/index.html b/test/index.html index aff53c4d..7c4867f4 100644 --- a/test/index.html +++ b/test/index.html @@ -40,7 +40,7 @@ Work Area
-
+
diff --git a/test/scratch.html b/test/scratch.html index 354d4442..54672080 100644 --- a/test/scratch.html +++ b/test/scratch.html @@ -43,7 +43,7 @@ Autorespond: +
diff --git a/www/_includes/demo_ui.html.liquid b/www/_includes/demo_ui.html.liquid index 5a5285e6..e61cd96a 100644 --- a/www/_includes/demo_ui.html.liquid +++ b/www/_includes/demo_ui.html.liquid @@ -5,13 +5,16 @@ bottom: 0; right: 0; left: 0; - max-height: 35vh; - height: 500px; + height: 50px; background-color: whitesmoke; border-top: 2px solid gray; overflow: scroll; margin: 0px; } + #demo-server-info.show { + max-height: 35vh; + height: 500px; + } #demo-activity { height:300px } @@ -23,9 +26,23 @@ #demo-canvas { margin-bottom: 500px; } + #request-info-toggler { + float: right; + } +
-
Server Requests
+
Server Requests ↑ Show
    diff --git a/www/_includes/layout.njk b/www/_includes/layout.njk index 3c5bf43c..2b2cb43a 100644 --- a/www/_includes/layout.njk +++ b/www/_includes/layout.njk @@ -35,21 +35,15 @@ docs
- events -
-
- headers -
- +
-
diff --git a/www/attributes.md b/www/attributes.md deleted file mode 100644 index 8f17e3a7..00000000 --- a/www/attributes.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -layout: layout.njk -title: kutty - Attributes ---- - -## Attribute Reference - -| Attribute | Description | -|-----------|-------------| -| [kt-boost](/attributes/kt-boost) | converts anchors and forms to use AJAX requests -| [kt-classes](/attributes/kt-classes) | timed modification of classes on an element -| [kt-confirm](/attributes/kt-confirm) | shows a confim() dialog before issuing a request -| [kt-delete](/attributes/kt-delete) | issue a `DELETE` to the specified URL -| [kt-error-url](/attributes/kt-error-url) | a URL to send client-side errors to -| [kt-get](/attributes/kt-get) | issue a `GET` to the specified URL -| [kt-include](/attributes/kt-include) | include additional data in AJAX requests -| [kt-indicator](/attributes/kt-indicator) | the element to put the `kutty-request` class on during the AJAX request -| [kt-patch](/attributes/kt-patch) | TODO - Description -| [kt-params](/attributes/kt-params) | filter the parameters that will be submitted with a request -| [kt-post](/attributes/kt-post) | TODO - Description -| kt-prompt | TODO - Description -| kt-push-url | TODO - Description -| [kt-put](/attributes/kt-put) | TODO - Description -| kt-select | TODO - Description -| kt-sse-src | TODO - Description -| [kt-swap](/attributes/kt-swap) | TODO - Description -| kt-swap-oob | TODO - Description -| kt-target | TODO - Description -| kt-trigger | TODO - Description \ No newline at end of file diff --git a/www/attributes/kt-indicator.md b/www/attributes/kt-indicator.md index b017eb8a..3f9c0f93 100644 --- a/www/attributes/kt-indicator.md +++ b/www/attributes/kt-indicator.md @@ -1,22 +1,83 @@ --- layout: layout.njk -title: kutty - kt-include +title: kutty - kt-indicator --- -## `kt-include` +## `kt-indicator` -The `kt-include` attribute allows you to include additional data beyond the [standard](/docs/#forms) -values. +The `kt-indicator` attribute allows you to specify the element that will have the `kutty-request` class +added to it for the duration of the request. This can be used to show spinners or progress indicators +while the request is in flight. -The value of this attribute is a CSS query selector of additional elements to include the values of. +The value of this attribute is a CSS query selector of the element or elements to apply the class to. + +Here is an example with a spinner adjacent to the button: ```html - + +
+``` + +When a request is in flight, this will cause the `kutty-request` class to be added to the `#spinner` +image. The image also has the `kutty-indicator` class on it, which defines an opacity transition +that will show the spinner: + +```css + .kutty-indicator{ + opacity:0; + transition: opacity 500ms ease-in; + } + .kutty-request .kutty-indicator{ + opacity:1 + } + .kutty-request.kutty-indicator{ + opacity:1 + } +``` + +If you would prefer a different effect for showing the spinner you could define and use your own indicator +CSS. Here is an example that uses `display` rather than opacity: + +```css + .kutty-indicator{ + display:none; + } + .kutty-request .my-indicator{ + display:inline; + } + .kutty-request.my-indicator{ + display:inline; + } +``` + +Note that the target of the `ic-indicator` selector need not be the exact element that you +want to show: it can be any element in the parent hierarchy of the indicator. + +Finally, note that the `kutty-request` class by default is added to the element causing +the request, so you can place an indicator inside of that element and not need to explictly +call it out with the `ic-indicator` attribute: + +```html + ``` -In addition to the normal variables included with this request, the value of the element with the -id `hidden-value` will be included. +### Demo + +This simulates what a spinner might look like in that situation: + + ### Notes + +* In the absence of an explicit indicator, the `kutty-request` class will be added to the element triggering the + request \ No newline at end of file diff --git a/www/events.md b/www/events.md deleted file mode 100644 index 3f278d14..00000000 --- a/www/events.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -layout: layout.njk -title: kutty - Events ---- - -## Event Reference - -| Event | Description | -|-------|-------------| -| afterOnLoad.kutty | TODO - Description -| afterSettle.kutty | TODO - Description -| afterSettle.kutty | TODO - Description -| afterSwap.kutty | TODO - Description -| beforeOnLoad.kutty | TODO - Description -| beforeRequest.kutty | TODO - Description -| beforeSwap.kutty | TODO - Description -| historyCacheMiss.kutty | TODO - Description -| historyCacheMissLoad.kutty | TODO - Description -| historyRestore.kutty | TODO - Description -| historyUpdate.kutty | TODO - Description -| initSSE.kutty | TODO - Description -| load.kutty | TODO - Description -| noSSESourceError.kutty | TODO - Description -| onLoadError.kutty | TODO - Description -| oobErrorNoTarget.kutty | TODO - Description -| prompt.kutty | TODO - Description -| responseError.kutty | TODO - Description -| sendError.kutty | TODO - Description -| sseError.kutty | TODO - Description -| swapError.kutty | TODO - Description -| values.kutty | TODO - Description diff --git a/www/patterns.md b/www/examples.md similarity index 81% rename from www/patterns.md rename to www/examples.md index fa534bc2..045e2766 100644 --- a/www/patterns.md +++ b/www/examples.md @@ -11,4 +11,4 @@ You can copy and paste them and then adjust them for your needs. | Pattern | Description | |-----------|-------------| -| [Click To Edit](/patterns/click-to-edit) | Demonstrates inline editing of a data object +| [Click To Edit](/examples/click-to-edit) | Demonstrates inline editing of a data object diff --git a/www/patterns/click-to-edit.md b/www/examples/click-to-edit.md similarity index 100% rename from www/patterns/click-to-edit.md rename to www/examples/click-to-edit.md diff --git a/www/headers.md b/www/headers.md deleted file mode 100644 index 16a03b76..00000000 --- a/www/headers.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -layout: layout.njk -title: kutty - Headers ---- - -## HTTP Headers - -### Request Headers -| Header | Description | -|-------|-------------| -| X-HTTP-Method-Override | TODO - Description -| X-KT-Request | TODO - Description -| X-KT-Trigger-Id | TODO - Description -| X-KT-Trigger-Name | TODO - Description -| X-KT-Target-Id | TODO - Description -| X-KT-Current-URL | TODO - Description -| X-KT-Prompt | TODO - Description -| X-KT-Event-Target | TODO - Description -| X-KT-Active-Element | TODO - Description -| X-KT-Active-Element-Value | TODO - Description - -### Response Headers -| Header | Description | -|-------|-------------| -| X-KT-Trigger | TODO - Description -| X-KT-Push | TODO - Description diff --git a/www/img/bars.svg b/www/img/bars.svg new file mode 100644 index 00000000..7cb07e65 --- /dev/null +++ b/www/img/bars.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/www/js/kutty.js b/www/js/kutty.js index b0b03e30..6d671843 100644 --- a/www/js/kutty.js +++ b/www/js/kutty.js @@ -122,6 +122,11 @@ var kutty = kutty || (function () { return trigger.split(/\s+/); } + function addRule(rule) { + var sheet = getDocument().styleSheets[0]; + sheet.insertRule(rule, sheet.cssRules.length); + } + //==================================================================== // Node processing //==================================================================== @@ -642,7 +647,7 @@ var kutty = kutty || (function () { // History Support //==================================================================== function getHistoryElement() { - var historyElt = getDocument().querySelector('.kt-history-elt'); + var historyElt = getDocument().querySelector('.kutty-history-elt'); return historyElt || getDocument().body; } @@ -697,7 +702,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-elt') || fragment; + fragment = fragment.querySelector('.kutty-history-elt') || fragment; settleImmediately(swapInnerHTML(getHistoryElement(), fragment)); } }; @@ -736,7 +741,7 @@ var kutty = kutty || (function () { indicators = [elt]; } forEach(indicators, function(ic) { - ic.classList[action].call(ic.classList, "kutty-show-indicator"); + ic.classList[action].call(ic.classList, "kutty-request"); }); } @@ -1055,6 +1060,11 @@ var kutty = kutty || (function () { } } + // insert kutty-indicator css rules + addRule(".kutty-indicator{opacity:0;transition: opacity 200ms ease-in;}"); + addRule(".kutty-request .kutty-indicator{opacity:1}"); + addRule(".kutty-request.kutty-indicator{opacity:1}"); + // initialize the document ready(function () { var body = getDocument().body; diff --git a/www/reference.md b/www/reference.md new file mode 100644 index 00000000..eedcf563 --- /dev/null +++ b/www/reference.md @@ -0,0 +1,89 @@ +--- +layout: layout.njk +title: kutty - Attributes +--- + +## Attribute Reference + +| Attribute | Description | +|-----------|-------------| +| [kt-boost](/attributes/kt-boost) | converts anchors and forms to use AJAX requests +| [kt-classes](/attributes/kt-classes) | timed modification of classes on an element +| [kt-confirm](/attributes/kt-confirm) | shows a confim() dialog before issuing a request +| [kt-delete](/attributes/kt-delete) | issue a `DELETE` to the specified URL +| [kt-error-url](/attributes/kt-error-url) | a URL to send client-side errors to +| [kt-get](/attributes/kt-get) | issue a `GET` to the specified URL +| [kt-include](/attributes/kt-include) | include additional data in AJAX requests +| [kt-indicator](/attributes/kt-indicator) | the element to put the `kutty-request` class on during the AJAX request +| [kt-patch](/attributes/kt-patch) | TODO - Description +| [kt-params](/attributes/kt-params) | filter the parameters that will be submitted with a request +| [kt-post](/attributes/kt-post) | TODO - Description +| kt-prompt | TODO - Description +| kt-push-url | TODO - Description +| [kt-put](/attributes/kt-put) | TODO - Description +| kt-select | TODO - Description +| kt-sse-src | TODO - Description +| [kt-swap](/attributes/kt-swap) | TODO - Description +| kt-swap-oob | TODO - Description +| kt-target | TODO - Description +| kt-trigger | TODO - Description + +## CSS Class Reference + +| Attribute | Description | +|-----------|-------------| +| kutty-request | TODO +| kutty-indicator | TODO +| kutty-history-elt | TODO +| kutty-swapping | TODO +| kutty-settling | TODO + + +## HTTP Header Reference + +### Request Headers +| Header | Description | +|-------|-------------| +| X-HTTP-Method-Override | TODO - Description +| X-KT-Request | TODO - Description +| X-KT-Trigger-Id | TODO - Description +| X-KT-Trigger-Name | TODO - Description +| X-KT-Target-Id | TODO - Description +| X-KT-Current-URL | TODO - Description +| X-KT-Prompt | TODO - Description +| X-KT-Event-Target | TODO - Description +| X-KT-Active-Element | TODO - Description +| X-KT-Active-Element-Value | TODO - Description + +### Response Headers +| Header | Description | +|-------|-------------| +| X-KT-Trigger | TODO - Description +| X-KT-Push | TODO - Description + +## Event Reference + +| Event | Description | +|-------|-------------| +| afterOnLoad.kutty | TODO - Description +| afterSettle.kutty | TODO - Description +| afterSettle.kutty | TODO - Description +| afterSwap.kutty | TODO - Description +| beforeOnLoad.kutty | TODO - Description +| beforeRequest.kutty | TODO - Description +| beforeSwap.kutty | TODO - Description +| historyCacheMiss.kutty | TODO - Description +| historyCacheMissLoad.kutty | TODO - Description +| historyRestore.kutty | TODO - Description +| historyUpdate.kutty | TODO - Description +| initSSE.kutty | TODO - Description +| load.kutty | TODO - Description +| noSSESourceError.kutty | TODO - Description +| onLoadError.kutty | TODO - Description +| oobErrorNoTarget.kutty | TODO - Description +| prompt.kutty | TODO - Description +| responseError.kutty | TODO - Description +| sendError.kutty | TODO - Description +| sseError.kutty | TODO - Description +| swapError.kutty | TODO - Description +| values.kutty | TODO - Description