Bespoke.js: The Road to 1KB

What?

bit.ly/diyslides

Google "bespoke.js"

Why?

< = 5KB

No dependencies

/*! Bespoke.js v0.3 © 2013 Mark Dalgleish, Licensed MIT */
!function(a, b){var c=function(a, b){var c=document.querySelector(a), g=[].slice.call(c.children, 0), h=g[0], i={}, k=function(a, b){g[a]&&(p("deactivate", q(h, b)), h=g[a], g.map(l), p("activate", q(h, b)), e(h, "active"), f(h, "inactive"))}, l=function(a, b){var c=b-g.indexOf(h), d=c>0?"after":"before";["before(-\\d+)?", "after(-\\d+)?", "active", "inactive"].map(f.bind(0, a)), a!=h&&["inactive", d, d+"-"+Math.abs(c)].map(e.bind(0, a))}, m=function(a, b){p("slide", q(g[a], b))&&k(a, b)}, n=function(a, b){var c=g.indexOf(h)+a;p(a>0?"next":"prev", q(h, b))&&k(c, b)}, o=function(a, b){return(i[a]||(i[a]=[])).push(b), function(){i[a]=i[a].filter(function(a){return a!=b})}}, p=function(a, b){return(i[a]||[]).reduce(function(a, c){return a&&c(b)!==!1}, !0)}, q=function(a, b){return b=b||{}, b.index=g.indexOf(a), b.slide=a, b}, r={on:o, fire:p, slide:m, next:n.bind(0, 1), prev:n.bind(0, -1), parent:c, slides:g};e(c, "parent"), g.map(function(a){e(a, "slide")});for(var s in b)j[s](r, b[s]);return k(0), d.push(r), r}, d=[], e=function(b, c){b.classList.add(a+"-"+c)}, f=function(b, c){b.className=b.className.replace(RegExp(a+"-"+c+"(\\s|$)", "g"), " ").trim()}, g=function(a){return function(b){d.map(function(c){c[a](b)})}}, h=function(a){return{from:function(b, d){return(d=d||{})[a]=!0, c(b, d)}}}, i=function(a){return function(b){var c, d;document.addEventListener("keydown", function(c){(34==c.which||32==c.which||"X"==a&&39==c.which||"Y"==a&&40==c.which)&&b.next(), (33==c.which||"X"==a&&37==c.which||"Y"==a&&38==c.which)&&b.prev()}), b.parent.addEventListener("touchstart", function(b){1==b.touches.length&&(c=b.touches[0]["page"+a], d=0)}), b.parent.addEventListener("touchmove", function(b){1==b.touches.length&&(b.preventDefault(), d=b.touches[0]["page"+a]-c)}), b.parent.addEventListener("touchend", function(){Math.abs(d)>50&&(d>0?b.prev():b.next())})}}, j={horizontal:i("X"), vertical:i("Y")};b[a]={from:c, slide:g("slide"), next:g("next"), prev:g("prev"), horizontal:h("horizontal"), vertical:h("vertical"), plugins:j}}("bespoke", this);

Feature request?

Just say no.

Want features?

Make it modular

grunt-micro

Google
"grunt-micro"

Limit that size

Code time!

forEach

for(var i=0;i<things.length;i++){
  doSomething(things[i]);
}

Vs.

things.forEach(doSomething);

Partial application

function(cls){ addClass(slide, cls); }

Vs.

addClass.bind(null, slide);

Function#bind returns a new function
with 'this' and arguments applied.

Hack time!

forEach ~> map

arr.forEach(doSomething);

Vs.

arr.map(doSomething);

Array#map returns an array, just don't use it.

Undefined fallbacks

if(obj)Object.keys(obj).forEach(foo);

Vs.

Object.keys(obj||{}).forEach(foo);

RegExp doesn't need 'new'

new RegExp(foobar);

Vs.

RegExp(foobar);

Don't believe me? Read the spec!

Assignment returns value

obj=obj||{};obj[prop] = true;

Vs.

(obj=obj||{})[prop] = true;

Double equals!

obj1 === obj2

Vs.

obj1 == obj2

Sorry Crockford, but
I know they're the same type.

Actual solution time!

Let's assume a lib like this

myLib({
  foo: true,
  bar: false,
  baz: 'quz'
});

Don't write it
like this

var myLib = function(options) {
  if (options.foo) doThis();
  if (options.bar) doSomeOtherStuff();
  if (options.baz) coverSomeWeirdEdgeCase();
};

Write it like this

var myLib = function(plugins) {
  for (var name in plugins) {
    var value = plugins[name];
    myLib.plugins[name](value);
  });
};
myLib.plugins.baz = function() {
  coverSomeWeirdEdgeCase();
}; // etc...

Why?

Tiny core library

Extremely modular

Repo per feature

Bower package per feature.

Seriously, why?

Yeoman.

Introducing...

generator-bespoke

$ npm install -g yo generator-bespoke$ yo bespoke

Generates bower.json

(Among other things)

{
  "name": "hello-world-bespoke",
  "version": "0.0.0",
  "dependencies": {
    "bespoke.js": "~0.2.0",
    "bespoke-bullets": "~0.2.0",
    "bespoke-hash": "~0.1.0",
    "bespoke-state": "~0.2.0",
    "prism": "gh-pages"
  }
}

Plus heaps more


Bonus!

GitHub Pages deploy task


Publishing your deck is stupid easy.

Demo time!

Google "generator-bespoke"

Thank you!

bit.ly/roadto1kb

@markdalgleish