Comparing version 0.0.17 to 0.0.18
68
app.js
@@ -11,3 +11,3 @@ var patch = require("snabbdom").init([ | ||
var model = options.model, | ||
view = options.view || Function.prototype, | ||
view = options.view || function () { return document.body }, | ||
routes = typeof view === "function" ? undefined : view, | ||
@@ -25,17 +25,16 @@ params = {}, | ||
// | ||
// only if there are routes. dispatch.setLocation is a wrapper for pushState | ||
// that causes the result view to be render. also intercept all anchor clicks | ||
// and make them call setLocation with anchor's pathname. | ||
// | ||
if (routes) { | ||
view = route(routes, location.pathname) | ||
view = route(routes, getHashOrPath()) | ||
dispatch.setLocation = function (data) { | ||
render(model, view = route(routes, data), node) | ||
history.pushState({}, "", data) | ||
if (history && history.pushState) { | ||
render(model, view = route(routes, data), node) | ||
history.pushState({}, "", data) | ||
} else { | ||
window.location.hash = data | ||
} | ||
} | ||
window.onpopstate = function () { | ||
render(model, view = route(routes, location.pathname), node) | ||
window[history && history.pushState ? "onpopstate" : "onhashchange"] = function () { | ||
render(model, view = route(routes, getHashOrPath()), node) | ||
} | ||
@@ -59,7 +58,8 @@ | ||
} | ||
function getHashOrPath() { | ||
return location.hash ? location.hash.substr(1) : location.pathname | ||
} | ||
} | ||
// | ||
// this is how we wrap dispatch("action", data) to dispatch.action(data). | ||
// | ||
for (var name in merge(merge({}, reducers), effects)) { | ||
@@ -70,3 +70,3 @@ if (reducers[name] && effects[name]) { | ||
// | ||
// wrap name in a closure, so we don't end up dispatching the same action | ||
// Wrap name in a closure, so we don't end up dispatching the same action | ||
// for all dispatch.action(data) calls. | ||
@@ -89,6 +89,2 @@ // | ||
// | ||
// ready calls cb when the dom is loaded. Should work in >=IE8. | ||
// | ||
function ready(cb) { | ||
@@ -100,8 +96,2 @@ document.addEventListener | ||
// | ||
// merge extends target with source properties. if the given source is a string or a number | ||
// literal, then returns the source as is. this lets you use a single number or string as | ||
// the initial model. | ||
// | ||
function merge(target, source) { | ||
@@ -114,7 +104,2 @@ for (var key in source) { | ||
// | ||
// render updates the DOM calling patch with the view. also mutates the current | ||
// node to the new one. | ||
// | ||
function render(model, view, lastNode) { | ||
@@ -124,9 +109,2 @@ patch(lastNode, node = view(model, dispatch)) | ||
// | ||
// dispatch calls an effect or reducer, aka sending an action. you can either use | ||
// dispatch("action", data) or dispatch.action(data). the latter looks better so | ||
// it's the style favored in the docs. sending an action updates the model and | ||
// renders the result node if the action corresponds to a reducer. | ||
// | ||
function dispatch(name, data) { | ||
@@ -151,15 +129,2 @@ hooks.onAction(name, data) | ||
// | ||
// route returns a params-wrapped view function whose key matches the given path. | ||
// | ||
// Default: * | ||
// Regexp: /users?/:name -> /user/foo | /users/foo and params -> { name: "foo" } | ||
// | ||
// the current solution consists in transforming each key to a regular expression, e.g, | ||
// | ||
// /users?/:name -> /^\/users?\/:([A-Za-z0-9_]+)/?$/ | ||
// | ||
// and use a stack to collect slugs that match each group capture.. | ||
// | ||
function route(routes, path) { | ||
@@ -190,2 +155,5 @@ for (var name in routes) { | ||
// | ||
// Translate each route to a regex, e.g, /users?/:id -> /^\/users?\/:([A-Za-z0-9_]+)/?$/ | ||
// | ||
function pathToRe(path) { | ||
@@ -192,0 +160,0 @@ var slugs = [], re = "^" + path |
@@ -1,1 +0,1 @@ | ||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.app=f()}})(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}({1:[function(require,module,exports){var patch=require("snabbdom").init([require("snabbdom/modules/class"),require("snabbdom/modules/props"),require("snabbdom/modules/style"),require("snabbdom/modules/attributes"),require("snabbdom/modules/eventlisteners")]);module.exports=function(t){function o(t){document.addEventListener?document.addEventListener("DOMContentLoaded",t):window.attachEvent("onload",t)}function n(t,o){for(var n in o)t[n]=o[n];return"string"==typeof o||"number"==typeof o?o:t}function e(t,o,n){patch(n,l=o(t,r))}function r(t,o){p.onAction(t,o);var i=f[t];if("function"==typeof i)return void i(a,r,o,p.onError);var c=s[t],d=a;if(void 0===c)throw new TypeError(t+" is not a reducer or effect");e(a=n(a,c(a,o)),u,l),p.onUpdate(d,a,o)}function i(t,o){function n(t){var o=[],n="^"+t.replace(/\//g,"\\/").replace(/:([A-Za-z0-9_]+)/g,function(t,n){return o.push(n),"([A-Za-z0-9_]+)"})+"/?$";return{exp:n,slugs:o}}for(var e in t)if("*"!==e){var r,i=n(e),a={};if(o.replace(new RegExp(i.exp,"g"),function(){for(var o=1;o<arguments.length-2;o++)a[i.slugs.shift()]=arguments[o];r=function(o,n){return t[e](o,n,a)}}),r)return r}return t["*"]}var a=t.model,u=t.view||Function.prototype,c="function"==typeof u?void 0:u,s=t.update||{},f=t.effects||{},d=t.subs||t.subscriptions||{},p=n({onAction:Function.prototype,onUpdate:Function.prototype,onError:function(t){throw t}},t.hooks),l=t.root||document.body.appendChild(document.createElement("div"));c&&(u=i(c,location.pathname),r.setLocation=function(t){e(a,u=i(c,t),l),history.pushState({},"",t)},window.onpopstate=function(){e(a,u=i(c,location.pathname),l)},window.onclick=function(t){if(!(t.metaKey||t.shiftKey||t.ctrlKey||t.altKey)){for(var o=t.target;o&&"a"!==o.localName;)o=o.parentNode;o&&o.host===location.host&&!o.hasAttribute("data-no-routing")&&(r.setLocation(t.target.pathname),t.preventDefault())}});for(var m in n(n({},s),f)){if(s[m]&&f[m])throw TypeError(m+" already defined as reducer or effect");!function(t){r[t]=function(o){r(t,o)}}(m)}o(function(){for(var t in d)d[t](a,r,p.onError)}),e(a,u,l)}},{snabbdom:9,"snabbdom/modules/attributes":4,"snabbdom/modules/class":5,"snabbdom/modules/eventlisteners":6,"snabbdom/modules/props":7,"snabbdom/modules/style":8}],2:[function(require,module,exports){function createElement(e){return document.createElement(e)}function createElementNS(e,t){return document.createElementNS(e,t)}function createTextNode(e){return document.createTextNode(e)}function insertBefore(e,t,n){e.insertBefore(t,n)}function removeChild(e,t){e.removeChild(t)}function appendChild(e,t){e.appendChild(t)}function parentNode(e){return e.parentElement}function nextSibling(e){return e.nextSibling}function tagName(e){return e.tagName}function setTextContent(e,t){e.textContent=t}module.exports={createElement:createElement,createElementNS:createElementNS,createTextNode:createTextNode,appendChild:appendChild,removeChild:removeChild,insertBefore:insertBefore,parentNode:parentNode,nextSibling:nextSibling,tagName:tagName,setTextContent:setTextContent}},{}],3:[function(require,module,exports){module.exports={array:Array.isArray,primitive:function(r){return"string"==typeof r||"number"==typeof r}}},{}],4:[function(require,module,exports){function updateAttrs(e,t){var a,r,l,s,o=t.elm,n=e.data.attrs,d=t.data.attrs;if(n||d){n=n||{},d=d||{};for(a in d)r=d[a],l=n[a],l!==r&&(!r&&booleanAttrsDict[a]?o.removeAttribute(a):(s=a.split(":"),s.length>1&&NamespaceURIs.hasOwnProperty(s[0])?o.setAttributeNS(NamespaceURIs[s[0]],a,r):o.setAttribute(a,r)));for(a in n)a in d||o.removeAttribute(a)}}for(var NamespaceURIs={xlink:"http://www.w3.org/1999/xlink"},booleanAttrs=["allowfullscreen","async","autofocus","autoplay","checked","compact","controls","declare","default","defaultchecked","defaultmuted","defaultselected","defer","disabled","draggable","enabled","formnovalidate","hidden","indeterminate","inert","ismap","itemscope","loop","multiple","muted","nohref","noresize","noshade","novalidate","nowrap","open","pauseonexit","readonly","required","reversed","scoped","seamless","selected","sortable","spellcheck","translate","truespeed","typemustmatch","visible"],booleanAttrsDict=Object.create(null),i=0,len=booleanAttrs.length;i<len;i++)booleanAttrsDict[booleanAttrs[i]]=!0;module.exports={create:updateAttrs,update:updateAttrs}},{}],5:[function(require,module,exports){function updateClass(a,s){var e,t,d=s.elm,l=a.data.class,o=s.data.class;if(l||o){l=l||{},o=o||{};for(t in l)o[t]||d.classList.remove(t);for(t in o)e=o[t],e!==l[t]&&d.classList[e?"add":"remove"](t)}}module.exports={create:updateClass,update:updateClass}},{}],6:[function(require,module,exports){function invokeHandler(e,n,t){if("function"==typeof e)e.call(n,t,n);else if("object"==typeof e)if("function"==typeof e[0])if(2===e.length)e[0].call(n,e[1],t,n);else{var i=e.slice(1);i.push(t),i.push(n),e[0].apply(n,i)}else for(var r=0;r<e.length;r++)invokeHandler(e[r])}function handleEvent(e,n){var t=e.type,i=n.data.on;i&&i[t]&&invokeHandler(i[t],n,e)}function createListener(){return function e(n){handleEvent(n,e.vnode)}}function updateEventListeners(e,n){var t,i=e.data.on,r=e.listener,a=e.elm,o=n&&n.data.on,s=n&&n.elm;if(i!==o){if(i&&r)if(o)for(t in i)o[t]||a.removeEventListener(t,r,!1);else for(t in i)a.removeEventListener(t,r,!1);if(o){var f=n.listener=e.listener||createListener();if(f.vnode=n,i)for(t in o)i[t]||s.addEventListener(t,f,!1);else for(t in o)s.addEventListener(t,f,!1)}}}module.exports={create:updateEventListeners,update:updateEventListeners,destroy:updateEventListeners}},{}],7:[function(require,module,exports){function updateProps(e,p){var a,o,r,t=p.elm,d=e.data.props,u=p.data.props;if(d||u){d=d||{},u=u||{};for(a in d)u[a]||delete t[a];for(a in u)o=u[a],r=d[a],r===o||"value"===a&&t[a]===o||(t[a]=o)}}module.exports={create:updateProps,update:updateProps}},{}],8:[function(require,module,exports){function setNextFrame(e,t,a){nextFrame(function(){e[t]=a})}function updateStyle(e,t){var a,n,r=t.elm,o=e.data.style,l=t.data.style;if(o||l){o=o||{},l=l||{};var i="delayed"in o;for(n in o)l[n]||(r.style[n]="");for(n in l)if(a=l[n],"delayed"===n)for(n in l.delayed)a=l.delayed[n],i&&a===o.delayed[n]||setNextFrame(r.style,n,a);else"remove"!==n&&a!==o[n]&&(r.style[n]=a)}}function applyDestroyStyle(e){var t,a,n=e.elm,r=e.data.style;if(r&&(t=r.destroy))for(a in t)n.style[a]=t[a]}function applyRemoveStyle(e,t){var a=e.data.style;if(!a||!a.remove)return void t();var n,r,o=e.elm,l=0,i=a.remove,y=0,d=[];for(n in i)d.push(n),o.style[n]=i[n];r=getComputedStyle(o);for(var f=r["transition-property"].split(", ");l<f.length;++l)d.indexOf(f[l])!==-1&&y++;o.addEventListener("transitionend",function(e){e.target===o&&--y,0===y&&t()})}var raf="undefined"!=typeof window&&window.requestAnimationFrame||setTimeout,nextFrame=function(e){raf(function(){raf(e)})};module.exports={create:updateStyle,update:updateStyle,destroy:applyDestroyStyle,remove:applyRemoveStyle}},{}],9:[function(require,module,exports){"use strict";function isUndef(e){return void 0===e}function isDef(e){return void 0!==e}function sameVnode(e,t){return e.key===t.key&&e.sel===t.sel}function createKeyToOldIdx(e,t,i){var n,o,r={};for(n=t;n<=i;++n)o=e[n].key,isDef(o)&&(r[o]=n);return r}function init(e,t){function i(e){var i=e.id?"#"+e.id:"",n=e.className?"."+e.className.split(" ").join("."):"";return VNode(t.tagName(e).toLowerCase()+i+n,{},[],void 0,e)}function n(e,i){return function(){if(0===--i){var n=t.parentNode(e);t.removeChild(n,e)}}}function o(e,i){var n,r=e.data;isDef(r)&&isDef(n=r.hook)&&isDef(n=n.init)&&(n(e),r=e.data);var s,f=e.children,d=e.sel;if(isDef(d)){var l=d.indexOf("#"),a=d.indexOf(".",l),m=l>0?l:d.length,c=a>0?a:d.length,u=l!==-1||a!==-1?d.slice(0,Math.min(m,c)):d;if(s=e.elm=isDef(r)&&isDef(n=r.ns)?t.createElementNS(n,u):t.createElement(u),m<c&&(s.id=d.slice(m+1,c)),a>0&&(s.className=d.slice(c+1).replace(/\./g," ")),is.array(f))for(n=0;n<f.length;++n)t.appendChild(s,o(f[n],i));else is.primitive(e.text)&&t.appendChild(s,t.createTextNode(e.text));for(n=0;n<h.create.length;++n)h.create[n](emptyNode,e);n=e.data.hook,isDef(n)&&(n.create&&n.create(emptyNode,e),n.insert&&i.push(e))}else s=e.elm=t.createTextNode(e.text);return e.elm}function r(e,i,n,r,s,f){for(;r<=s;++r)t.insertBefore(e,o(n[r],f),i)}function s(e){var t,i,n=e.data;if(isDef(n)){for(isDef(t=n.hook)&&isDef(t=t.destroy)&&t(e),t=0;t<h.destroy.length;++t)h.destroy[t](e);if(isDef(t=e.children))for(i=0;i<e.children.length;++i)s(e.children[i])}}function f(e,i,o,r){for(;o<=r;++o){var f,d,l,a=i[o];if(isDef(a))if(isDef(a.sel)){for(s(a),d=h.remove.length+1,l=n(a.elm,d),f=0;f<h.remove.length;++f)h.remove[f](a,l);isDef(f=a.data)&&isDef(f=f.hook)&&isDef(f=f.remove)?f(a,l):l()}else t.removeChild(e,a.elm)}}function d(e,i,n,s){for(var d,a,m,h,c=0,u=0,p=i.length-1,v=i[0],D=i[p],g=n.length-1,x=n[0],k=n[g];c<=p&&u<=g;)isUndef(v)?v=i[++c]:isUndef(D)?D=i[--p]:sameVnode(v,x)?(l(v,x,s),v=i[++c],x=n[++u]):sameVnode(D,k)?(l(D,k,s),D=i[--p],k=n[--g]):sameVnode(v,k)?(l(v,k,s),t.insertBefore(e,v.elm,t.nextSibling(D.elm)),v=i[++c],k=n[--g]):sameVnode(D,x)?(l(D,x,s),t.insertBefore(e,D.elm,v.elm),D=i[--p],x=n[++u]):(isUndef(d)&&(d=createKeyToOldIdx(i,c,p)),a=d[x.key],isUndef(a)?(t.insertBefore(e,o(x,s),v.elm),x=n[++u]):(m=i[a],l(m,x,s),i[a]=void 0,t.insertBefore(e,m.elm,v.elm),x=n[++u]));c>p?(h=isUndef(n[g+1])?null:n[g+1].elm,r(e,h,n,u,g,s)):u>g&&f(e,i,c,p)}function l(e,i,n){var s,l;isDef(s=i.data)&&isDef(l=s.hook)&&isDef(s=l.prepatch)&&s(e,i);var a=i.elm=e.elm,m=e.children,c=i.children;if(e!==i){if(!sameVnode(e,i)){var u=t.parentNode(e.elm);return a=o(i,n),t.insertBefore(u,a,e.elm),void f(u,[e],0,0)}if(isDef(i.data)){for(s=0;s<h.update.length;++s)h.update[s](e,i);s=i.data.hook,isDef(s)&&isDef(s=s.update)&&s(e,i)}isUndef(i.text)?isDef(m)&&isDef(c)?m!==c&&d(a,m,c,n):isDef(c)?(isDef(e.text)&&t.setTextContent(a,""),r(a,null,c,0,c.length-1,n)):isDef(m)?f(a,m,0,m.length-1):isDef(e.text)&&t.setTextContent(a,""):e.text!==i.text&&t.setTextContent(a,i.text),isDef(l)&&isDef(s=l.postpatch)&&s(e,i)}}var a,m,h={};for(isUndef(t)&&(t=domApi),a=0;a<hooks.length;++a)for(h[hooks[a]]=[],m=0;m<e.length;++m)void 0!==e[m][hooks[a]]&&h[hooks[a]].push(e[m][hooks[a]]);return function(e,n){var r,s,d,a=[];for(r=0;r<h.pre.length;++r)h.pre[r]();for(isUndef(e.sel)&&(e=i(e)),sameVnode(e,n)?l(e,n,a):(s=e.elm,d=t.parentNode(s),o(n,a),null!==d&&(t.insertBefore(d,n.elm,t.nextSibling(s)),f(d,[e],0,0))),r=0;r<a.length;++r)a[r].data.hook.insert(a[r]);for(r=0;r<h.post.length;++r)h.post[r]();return n}}var VNode=require("./vnode"),is=require("./is"),domApi=require("./htmldomapi"),emptyNode=VNode("",{},[],void 0,void 0),hooks=["create","update","remove","destroy","pre","post"];module.exports={init:init}},{"./htmldomapi":2,"./is":3,"./vnode":10}],10:[function(require,module,exports){module.exports=function(e,t,d,o,r){var i=void 0===t?void 0:t.key;return{sel:e,data:t,children:d,text:o,elm:r,key:i}}},{}]},{},[1])(1)}); | ||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.app=f()}})(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}({1:[function(require,module,exports){var patch=require("snabbdom").init([require("snabbdom/modules/class"),require("snabbdom/modules/props"),require("snabbdom/modules/style"),require("snabbdom/modules/attributes"),require("snabbdom/modules/eventlisteners")]);module.exports=function(t){function o(){return location.hash?location.hash.substr(1):location.pathname}function n(t){document.addEventListener?document.addEventListener("DOMContentLoaded",t):window.attachEvent("onload",t)}function e(t,o){for(var n in o)t[n]=o[n];return"string"==typeof o||"number"==typeof o?o:t}function r(t,o,n){patch(n,l=o(t,i))}function i(t,o){h.onAction(t,o);var n=f[t];if("function"==typeof n)return void n(u,i,o,h.onError);var a=d[t],c=u;if(void 0===a)throw new TypeError(t+" is not a reducer or effect");r(u=e(u,a(u,o)),s,l),h.onUpdate(c,u,o)}function a(t,o){function n(t){var o=[],n="^"+t.replace(/\//g,"\\/").replace(/:([A-Za-z0-9_]+)/g,function(t,n){return o.push(n),"([A-Za-z0-9_]+)"})+"/?$";return{exp:n,slugs:o}}for(var e in t)if("*"!==e){var r,i=n(e),a={};if(o.replace(new RegExp(i.exp,"g"),function(){for(var o=1;o<arguments.length-2;o++)a[i.slugs.shift()]=arguments[o];r=function(o,n){return t[e](o,n,a)}}),r)return r}return t["*"]}var u=t.model,s=t.view||function(){return document.body},c="function"==typeof s?void 0:s,d=t.update||{},f=t.effects||{},p=t.subs||t.subscriptions||{},h=e({onAction:Function.prototype,onUpdate:Function.prototype,onError:function(t){throw t}},t.hooks),l=t.root||document.body.appendChild(document.createElement("div"));c&&(s=a(c,o()),i.setLocation=function(t){history&&history.pushState?(r(u,s=a(c,t),l),history.pushState({},"",t)):window.location.hash=t},window[history&&history.pushState?"onpopstate":"onhashchange"]=function(){r(u,s=a(c,o()),l)},window.onclick=function(t){if(!(t.metaKey||t.shiftKey||t.ctrlKey||t.altKey)){for(var o=t.target;o&&"a"!==o.localName;)o=o.parentNode;o&&o.host===location.host&&!o.hasAttribute("data-no-routing")&&(i.setLocation(t.target.pathname),t.preventDefault())}});for(var m in e(e({},d),f)){if(d[m]&&f[m])throw TypeError(m+" already defined as reducer or effect");!function(t){i[t]=function(o){i(t,o)}}(m)}n(function(){for(var t in p)p[t](u,i,h.onError)}),r(u,s,l)}},{snabbdom:9,"snabbdom/modules/attributes":4,"snabbdom/modules/class":5,"snabbdom/modules/eventlisteners":6,"snabbdom/modules/props":7,"snabbdom/modules/style":8}],2:[function(require,module,exports){function createElement(e){return document.createElement(e)}function createElementNS(e,t){return document.createElementNS(e,t)}function createTextNode(e){return document.createTextNode(e)}function insertBefore(e,t,n){e.insertBefore(t,n)}function removeChild(e,t){e.removeChild(t)}function appendChild(e,t){e.appendChild(t)}function parentNode(e){return e.parentElement}function nextSibling(e){return e.nextSibling}function tagName(e){return e.tagName}function setTextContent(e,t){e.textContent=t}module.exports={createElement:createElement,createElementNS:createElementNS,createTextNode:createTextNode,appendChild:appendChild,removeChild:removeChild,insertBefore:insertBefore,parentNode:parentNode,nextSibling:nextSibling,tagName:tagName,setTextContent:setTextContent}},{}],3:[function(require,module,exports){module.exports={array:Array.isArray,primitive:function(r){return"string"==typeof r||"number"==typeof r}}},{}],4:[function(require,module,exports){function updateAttrs(e,t){var a,r,l,s,o=t.elm,n=e.data.attrs,d=t.data.attrs;if(n||d){n=n||{},d=d||{};for(a in d)r=d[a],l=n[a],l!==r&&(!r&&booleanAttrsDict[a]?o.removeAttribute(a):(s=a.split(":"),s.length>1&&NamespaceURIs.hasOwnProperty(s[0])?o.setAttributeNS(NamespaceURIs[s[0]],a,r):o.setAttribute(a,r)));for(a in n)a in d||o.removeAttribute(a)}}for(var NamespaceURIs={xlink:"http://www.w3.org/1999/xlink"},booleanAttrs=["allowfullscreen","async","autofocus","autoplay","checked","compact","controls","declare","default","defaultchecked","defaultmuted","defaultselected","defer","disabled","draggable","enabled","formnovalidate","hidden","indeterminate","inert","ismap","itemscope","loop","multiple","muted","nohref","noresize","noshade","novalidate","nowrap","open","pauseonexit","readonly","required","reversed","scoped","seamless","selected","sortable","spellcheck","translate","truespeed","typemustmatch","visible"],booleanAttrsDict=Object.create(null),i=0,len=booleanAttrs.length;i<len;i++)booleanAttrsDict[booleanAttrs[i]]=!0;module.exports={create:updateAttrs,update:updateAttrs}},{}],5:[function(require,module,exports){function updateClass(a,s){var e,t,d=s.elm,l=a.data.class,o=s.data.class;if(l||o){l=l||{},o=o||{};for(t in l)o[t]||d.classList.remove(t);for(t in o)e=o[t],e!==l[t]&&d.classList[e?"add":"remove"](t)}}module.exports={create:updateClass,update:updateClass}},{}],6:[function(require,module,exports){function invokeHandler(e,n,t){if("function"==typeof e)e.call(n,t,n);else if("object"==typeof e)if("function"==typeof e[0])if(2===e.length)e[0].call(n,e[1],t,n);else{var i=e.slice(1);i.push(t),i.push(n),e[0].apply(n,i)}else for(var r=0;r<e.length;r++)invokeHandler(e[r])}function handleEvent(e,n){var t=e.type,i=n.data.on;i&&i[t]&&invokeHandler(i[t],n,e)}function createListener(){return function e(n){handleEvent(n,e.vnode)}}function updateEventListeners(e,n){var t,i=e.data.on,r=e.listener,a=e.elm,o=n&&n.data.on,s=n&&n.elm;if(i!==o){if(i&&r)if(o)for(t in i)o[t]||a.removeEventListener(t,r,!1);else for(t in i)a.removeEventListener(t,r,!1);if(o){var f=n.listener=e.listener||createListener();if(f.vnode=n,i)for(t in o)i[t]||s.addEventListener(t,f,!1);else for(t in o)s.addEventListener(t,f,!1)}}}module.exports={create:updateEventListeners,update:updateEventListeners,destroy:updateEventListeners}},{}],7:[function(require,module,exports){function updateProps(e,p){var a,o,r,t=p.elm,d=e.data.props,u=p.data.props;if(d||u){d=d||{},u=u||{};for(a in d)u[a]||delete t[a];for(a in u)o=u[a],r=d[a],r===o||"value"===a&&t[a]===o||(t[a]=o)}}module.exports={create:updateProps,update:updateProps}},{}],8:[function(require,module,exports){function setNextFrame(e,t,a){nextFrame(function(){e[t]=a})}function updateStyle(e,t){var a,n,r=t.elm,o=e.data.style,l=t.data.style;if(o||l){o=o||{},l=l||{};var i="delayed"in o;for(n in o)l[n]||(r.style[n]="");for(n in l)if(a=l[n],"delayed"===n)for(n in l.delayed)a=l.delayed[n],i&&a===o.delayed[n]||setNextFrame(r.style,n,a);else"remove"!==n&&a!==o[n]&&(r.style[n]=a)}}function applyDestroyStyle(e){var t,a,n=e.elm,r=e.data.style;if(r&&(t=r.destroy))for(a in t)n.style[a]=t[a]}function applyRemoveStyle(e,t){var a=e.data.style;if(!a||!a.remove)return void t();var n,r,o=e.elm,l=0,i=a.remove,y=0,d=[];for(n in i)d.push(n),o.style[n]=i[n];r=getComputedStyle(o);for(var f=r["transition-property"].split(", ");l<f.length;++l)d.indexOf(f[l])!==-1&&y++;o.addEventListener("transitionend",function(e){e.target===o&&--y,0===y&&t()})}var raf="undefined"!=typeof window&&window.requestAnimationFrame||setTimeout,nextFrame=function(e){raf(function(){raf(e)})};module.exports={create:updateStyle,update:updateStyle,destroy:applyDestroyStyle,remove:applyRemoveStyle}},{}],9:[function(require,module,exports){"use strict";function isUndef(e){return void 0===e}function isDef(e){return void 0!==e}function sameVnode(e,t){return e.key===t.key&&e.sel===t.sel}function createKeyToOldIdx(e,t,i){var n,o,r={};for(n=t;n<=i;++n)o=e[n].key,isDef(o)&&(r[o]=n);return r}function init(e,t){function i(e){var i=e.id?"#"+e.id:"",n=e.className?"."+e.className.split(" ").join("."):"";return VNode(t.tagName(e).toLowerCase()+i+n,{},[],void 0,e)}function n(e,i){return function(){if(0===--i){var n=t.parentNode(e);t.removeChild(n,e)}}}function o(e,i){var n,r=e.data;isDef(r)&&isDef(n=r.hook)&&isDef(n=n.init)&&(n(e),r=e.data);var s,f=e.children,d=e.sel;if(isDef(d)){var l=d.indexOf("#"),a=d.indexOf(".",l),m=l>0?l:d.length,c=a>0?a:d.length,u=l!==-1||a!==-1?d.slice(0,Math.min(m,c)):d;if(s=e.elm=isDef(r)&&isDef(n=r.ns)?t.createElementNS(n,u):t.createElement(u),m<c&&(s.id=d.slice(m+1,c)),a>0&&(s.className=d.slice(c+1).replace(/\./g," ")),is.array(f))for(n=0;n<f.length;++n)t.appendChild(s,o(f[n],i));else is.primitive(e.text)&&t.appendChild(s,t.createTextNode(e.text));for(n=0;n<h.create.length;++n)h.create[n](emptyNode,e);n=e.data.hook,isDef(n)&&(n.create&&n.create(emptyNode,e),n.insert&&i.push(e))}else s=e.elm=t.createTextNode(e.text);return e.elm}function r(e,i,n,r,s,f){for(;r<=s;++r)t.insertBefore(e,o(n[r],f),i)}function s(e){var t,i,n=e.data;if(isDef(n)){for(isDef(t=n.hook)&&isDef(t=t.destroy)&&t(e),t=0;t<h.destroy.length;++t)h.destroy[t](e);if(isDef(t=e.children))for(i=0;i<e.children.length;++i)s(e.children[i])}}function f(e,i,o,r){for(;o<=r;++o){var f,d,l,a=i[o];if(isDef(a))if(isDef(a.sel)){for(s(a),d=h.remove.length+1,l=n(a.elm,d),f=0;f<h.remove.length;++f)h.remove[f](a,l);isDef(f=a.data)&&isDef(f=f.hook)&&isDef(f=f.remove)?f(a,l):l()}else t.removeChild(e,a.elm)}}function d(e,i,n,s){for(var d,a,m,h,c=0,u=0,p=i.length-1,v=i[0],D=i[p],g=n.length-1,x=n[0],k=n[g];c<=p&&u<=g;)isUndef(v)?v=i[++c]:isUndef(D)?D=i[--p]:sameVnode(v,x)?(l(v,x,s),v=i[++c],x=n[++u]):sameVnode(D,k)?(l(D,k,s),D=i[--p],k=n[--g]):sameVnode(v,k)?(l(v,k,s),t.insertBefore(e,v.elm,t.nextSibling(D.elm)),v=i[++c],k=n[--g]):sameVnode(D,x)?(l(D,x,s),t.insertBefore(e,D.elm,v.elm),D=i[--p],x=n[++u]):(isUndef(d)&&(d=createKeyToOldIdx(i,c,p)),a=d[x.key],isUndef(a)?(t.insertBefore(e,o(x,s),v.elm),x=n[++u]):(m=i[a],l(m,x,s),i[a]=void 0,t.insertBefore(e,m.elm,v.elm),x=n[++u]));c>p?(h=isUndef(n[g+1])?null:n[g+1].elm,r(e,h,n,u,g,s)):u>g&&f(e,i,c,p)}function l(e,i,n){var s,l;isDef(s=i.data)&&isDef(l=s.hook)&&isDef(s=l.prepatch)&&s(e,i);var a=i.elm=e.elm,m=e.children,c=i.children;if(e!==i){if(!sameVnode(e,i)){var u=t.parentNode(e.elm);return a=o(i,n),t.insertBefore(u,a,e.elm),void f(u,[e],0,0)}if(isDef(i.data)){for(s=0;s<h.update.length;++s)h.update[s](e,i);s=i.data.hook,isDef(s)&&isDef(s=s.update)&&s(e,i)}isUndef(i.text)?isDef(m)&&isDef(c)?m!==c&&d(a,m,c,n):isDef(c)?(isDef(e.text)&&t.setTextContent(a,""),r(a,null,c,0,c.length-1,n)):isDef(m)?f(a,m,0,m.length-1):isDef(e.text)&&t.setTextContent(a,""):e.text!==i.text&&t.setTextContent(a,i.text),isDef(l)&&isDef(s=l.postpatch)&&s(e,i)}}var a,m,h={};for(isUndef(t)&&(t=domApi),a=0;a<hooks.length;++a)for(h[hooks[a]]=[],m=0;m<e.length;++m)void 0!==e[m][hooks[a]]&&h[hooks[a]].push(e[m][hooks[a]]);return function(e,n){var r,s,d,a=[];for(r=0;r<h.pre.length;++r)h.pre[r]();for(isUndef(e.sel)&&(e=i(e)),sameVnode(e,n)?l(e,n,a):(s=e.elm,d=t.parentNode(s),o(n,a),null!==d&&(t.insertBefore(d,n.elm,t.nextSibling(s)),f(d,[e],0,0))),r=0;r<a.length;++r)a[r].data.hook.insert(a[r]);for(r=0;r<h.post.length;++r)h.post[r]();return n}}var VNode=require("./vnode"),is=require("./is"),domApi=require("./htmldomapi"),emptyNode=VNode("",{},[],void 0,void 0),hooks=["create","update","remove","destroy","pre","post"];module.exports={init:init}},{"./htmldomapi":2,"./is":3,"./vnode":10}],10:[function(require,module,exports){module.exports=function(e,t,d,o,r){var i=void 0===t?void 0:t.key;return{sel:e,data:t,children:d,text:o,elm:r,key:i}}},{}]},{},[1])(1)}); |
{ | ||
"name": "flea", | ||
"description": "Tiny UI library based in Snabbdom and ES6 tagged template literals", | ||
"version": "0.0.17", | ||
"version": "0.0.18", | ||
"main": "index.js", | ||
"author": "Jorge Bucaran", | ||
"license": "MIT", | ||
"repository": "jbucaran/flea", | ||
"repository": "fleajs/flea", | ||
"keywords": [ | ||
@@ -10,0 +10,0 @@ "snabbdom", |
193
README.md
# flea | ||
Flea is a tiny JavaScript UI library based in [Snabbdom] and ES6 tagged template literals with [Hyperx]. | ||
Flea is a tiny JavaScript UI library based in [Snabbdom] and ES6 tagged template literals. | ||
The API and state management is inspired by the [Elm Architecture] and [choo]. | ||
[See live examples](https://flea.gomix.me/). | ||
@@ -13,8 +13,17 @@ ## Install | ||
## Example | ||
## Examples | ||
A basic counter app. See [fiddle](https://jsfiddle.net/jbucaran/epo7fexz/10/). | ||
### [Hello world](http://codepen.io/jbucaran/pen/Qdwpxy?editors=0010) | ||
```js | ||
app({ | ||
model: "Hi.", | ||
view: model => html`<h1>${model}</h1>` | ||
}) | ||
``` | ||
### [Counter](http://codepen.io/jbucaran/pen/zNxZLP?editors=0010) | ||
```js | ||
app({ | ||
model: 0, | ||
@@ -34,7 +43,45 @@ update: { | ||
[See more examples](https://flea.gomix.me/). | ||
### [Heading bound to input](http://codepen.io/jbucaran/pen/ggbmdN?editors=0010#) | ||
```js | ||
app({ | ||
model: "", | ||
update: { | ||
text: (_, value) => value | ||
}, | ||
view: (model, msg) => html` | ||
<div> | ||
<h1>Hi${model ? " " + model : ""}.</h1> | ||
<input oninput=${e => msg.text(e.target.value)} /> | ||
</div>` | ||
}) | ||
``` | ||
## Usage | ||
CDN | ||
```html | ||
<script src="https://cdn.rawgit.com/fleajs/flea/master/dist/flea.min.js"></script> | ||
<script src="https://cdn.rawgit.com/fleajs/flea/master/dist/html.min.js"></script> | ||
``` | ||
Browserify | ||
``` | ||
browserify index.js > bundle.js | ||
``` | ||
```html | ||
<!doctype html> | ||
<html> | ||
<body> | ||
<script src="bundle.js"></script> | ||
</body> | ||
</html> | ||
``` | ||
## API | ||
### html | ||
## html | ||
@@ -51,44 +98,107 @@ Use `html` to compose HTML elements. | ||
### app | ||
## app | ||
The `app` function takes an object with any of the following properties. | ||
Use `app` to create your app. The `app` function receives an object with any of the following properties. | ||
#### model | ||
### model | ||
An value or object that represents the state of your app. You don't modify the model directly, instead, dispatch actions that describe how the model will change. See [view](#view). | ||
A value or object that represents the state of your app. | ||
#### update | ||
You never modify the model directly, instead, send actions describing how the model should change. See [view](#view). | ||
The update object exposes reducer functions. A reducer describes how the model will change for a given action and can return a new model or part of a model. If a reducer returns part of a model, it will be merged back into the current model. | ||
### update | ||
Reducers have a signature `(model, data)`, where `model` is the current model, and `data` is any data passed into the function. | ||
Object composed of functions known as reducers. These are a kind of action you can send. | ||
You call reducers inside a view, effect or subscription. | ||
A reducer describes how the model should change and returns a new model or part of a model. | ||
#### view | ||
```js | ||
const update = { | ||
increment: model + 1, | ||
decrement: model - 1 | ||
} | ||
``` | ||
The view is a function that returns HTML via the `html` function. | ||
If a reducer returns part of a model, that part will be merged with the current model. | ||
The view has a signature `(model, msg)`, where `model` is the current model, and `msg` is an object you use to call reducers / cause effects. | ||
You call reducers inside a [view](#view), [effect](#effect) or [subscription](#subs). | ||
Reducers have a signature `(model, data)`, where | ||
* `model` is the current model, and | ||
* `data` is the data sent along with the action. | ||
### view | ||
The view is a function that returns HTML using the `html` function. | ||
The view has a signature `(model, msg, params)`, where | ||
* `model` is the current model, | ||
* `msg` is the object you use to send actions (call reducers or cause effects) and | ||
* `params` are the route parameters if the view belongs to a [route](#routing). | ||
```js | ||
msg.name(data) | ||
msg.action(data) | ||
``` | ||
or if you prefer | ||
#### Routing | ||
Instead of a view as a single function, declare an object with multiple views and use the route path as the key. | ||
```js | ||
msg("name", data) | ||
app({ | ||
view: { | ||
"*": (model, msg) => {} | ||
"/": (model, msg) => {} | ||
"/:slug": (model, msg, params) => {} | ||
} | ||
}) | ||
``` | ||
#### effects | ||
* `*` default route used when no other route matches, e.g, 404 page, etc. | ||
Effects are often asynchronous and cause side effects, like writing to a database, or sending requests to servers. When they are done, they often dispatch an action. | ||
* `/` index route | ||
Effects have a signature `(model, msg, error)`, where `model` is the current model, `msg` is an object you use to call reducers / cause effects (see [view](#view)), and `error` is a function you may call with an error if something goes wrong. | ||
* `/:a/:b/:c` matches a route with three components using the regular expression `[A-Za-z0-9]+` and stores each captured group in the params object, which is passed into the view function. | ||
#### subs | ||
The route path syntax is based in the same syntax found in [Express](https://expressjs.com/en/guide/routing.html). | ||
Subscriptions are functions that run only once when the [DOM is ready](https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded). Use a subscription to register global events, like mouse or keyboard listeners. | ||
##### setLocation | ||
To update the address bar relative location and render a different view, use `msg.setLocation(path)`. | ||
##### Anchors | ||
As a bonus, we intercept all `<a href="/path">...</a>` clicks and call `msg.setLocation("/path")` for you. If you want to opt out of this, add the custom attribute `data-no-routing` to any anchor element that should be handled differently. | ||
```html | ||
<a data-no-routing>...</a> | ||
``` | ||
### effects | ||
Effects cause side effects and are often asynchronous, like writing to a database, or sending requests to servers. They can dispatch other actions too. | ||
Effects have a signature `(model, msg, error)`, where | ||
* `model` is the current model, | ||
* `msg` is an object you use to call reducers / cause effects (see [view](#view)), and | ||
* `error` is a function you may call with an error if something goes wrong. | ||
```js | ||
const update = { | ||
add: model => model + 1 | ||
} | ||
const effects = { | ||
waitThenAdd: (_, msg) => setTimeout(msg.add, 1000) | ||
} | ||
``` | ||
### subs | ||
Subscriptions are functions that run once when the [DOM is ready](https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded). Use a subscription to register global events, like mouse or keyboard listeners. | ||
While reducers and effects are actions _you_ cause, you can't call subscriptions directly. | ||
@@ -98,36 +208,37 @@ | ||
#### hooks | ||
```js | ||
const update = { | ||
move: (model, { x, y }) => ({ x, y }) | ||
} | ||
Hooks are functions called when certain events happen across the app. You can use hooks to implement middleware, loggers, etc. | ||
const subs = [ | ||
(_, msg) => addEventListener("mousemove", e => msg.move({ x: e.clientX, y: e.clientY })) | ||
] | ||
``` | ||
##### onUpdate | ||
### hooks | ||
Hooks are functions called for certain events during the lifetime of the app. You can use hooks to implement middleware, loggers, etc. | ||
#### onUpdate | ||
Called when the model changes. Signature `(lastModel, newModel, data)`. | ||
##### onAction | ||
#### onAction | ||
Called when an action (reducer or effect) is dispatched. Signature `(name, data)`. | ||
##### onError | ||
#### onError | ||
Called when you use the `error` function inside a subscription or effect. If you don't use this hook, the default behavior is to throw. Signature `(err)`. | ||
#### root | ||
### root | ||
The root is the HTML element that will serve as a container for your app. If none is given, a `div` element is appended to the document.body. | ||
## FAQ | ||
### What about choo or yo-yo? | ||
I like both, but I enjoyed yo-yo the best. I even wrote a tiny [module](https://www.npmjs.com/package/yo-yo-app) to help me structure apps with it. I found using only yo-yo too limiting, and choo too frameworky. | ||
In particular, I didn't like some of choo choices like namespaces, including a router, models as containers for state and [morphdom](https://github.com/patrick-steele-idem/morphdom). | ||
See also [virtual dom benchmarks](http://vdom-benchmark.github.io/vdom-benchmark/). | ||
[Snabbdom]: https://github.com/snabbdom/snabbdom | ||
[Hyperx]: https://github.com/substack/hyperx | ||
[Elm Architecture]: https://guide.elm-lang.org/architecture | ||
[yo-yo]: https://github.com/maxogden/yo-yo | ||
[choo]: https://github.com/yoshuawuyts/choo |
Sorry, the diff of this file is not supported yet
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
72323
11
240
0
137