updated app

This commit is contained in:
2012-05-30 23:00:06 -04:00
parent 6a753904b7
commit da6ad88d48
5545 changed files with 1101709 additions and 60 deletions

2
node_modules/derby-examples/sink/Makefile generated vendored Normal file
View File

@@ -0,0 +1,2 @@
compile:
./node_modules/coffee-script/bin/coffee -bw -o ./lib -c ./src

View File

@@ -0,0 +1,118 @@
// Generated by CoffeeScript 1.3.1
var N, app, get, ready, render, _ref;
_ref = app = require('./index'), get = _ref.get, ready = _ref.ready;
render = require('./shared').render;
N = 100;
get('/bindings-bench', function(page, model) {
var boxes, i, _i;
boxes = [];
for (i = _i = 0; 0 <= N ? _i < N : _i > N; i = 0 <= N ? ++_i : --_i) {
boxes.push({
count: 0,
top: 0,
left: 0,
color: 0,
content: 0,
i: i
});
}
model.set('_boxes', boxes);
return render(page, 'bindingsBench', {
modes: ['setProperty', 'setBox', 'setAll']
});
});
ready(function(model) {
var boxValue, boxes, fn, frames, modes, run, setAll, setBox, setProperty, start, tickBox, tickProperty, timeout;
boxes = model.at('_boxes');
tickProperty = function(box) {
var count;
count = box.incr('count');
box.set('top', Math.sin(count / 10) * 10);
box.set('left', Math.cos(count / 10) * 10);
box.set('color', count % 255);
return box.set('content', count % 100);
};
setProperty = function() {
var i, _i;
for (i = _i = 0; 0 <= N ? _i < N : _i > N; i = 0 <= N ? ++_i : --_i) {
tickProperty(boxes.at(i));
}
};
tickBox = function(box, i) {
var count;
count = box.get('count') + 1;
return box.set({
count: count,
top: Math.sin(count / 10) * 10,
left: Math.cos(count / 10) * 10,
color: count % 255,
content: count % 100,
i: i
});
};
setBox = function() {
var i, _i;
for (i = _i = 0; 0 <= N ? _i < N : _i > N; i = 0 <= N ? ++_i : --_i) {
tickBox(boxes.at(i), i);
}
};
boxValue = function(box, i) {
var count;
count = box.count + 1;
return {
count: count,
top: Math.sin(count / 10) * 10,
left: Math.cos(count / 10) * 10,
color: count % 255,
content: count % 100,
i: i
};
};
setAll = function() {
var box, i, previous, value, _i, _len;
previous = boxes.get();
value = [];
for (i = _i = 0, _len = previous.length; _i < _len; i = ++_i) {
box = previous[i];
value.push(boxValue(box, i));
}
return boxes.set(value);
};
frames = 0;
start = fn = timeout = null;
run = function() {
var fps;
fn();
if (frames++ === 20) {
fps = frames * 1000 / (new Date - start);
model.set('_fps', fps.toFixed(1));
frames = 0;
start = +(new Date);
}
return timeout = setTimeout(run, 0);
};
modes = {
setProperty: setProperty,
setBox: setBox,
setAll: setAll
};
app.start = function(e, el) {
var mode;
clearTimeout(timeout);
mode = el.innerHTML;
model.set('_bindProperties', mode === 'setProperty');
model.set('_mode', mode);
fn = modes[mode];
frames = 0;
start = +(new Date);
return run();
};
return app.stop = function() {
return clearTimeout(timeout);
};
});

62
node_modules/derby-examples/sink/lib/app/home.js generated vendored Normal file
View File

@@ -0,0 +1,62 @@
// Generated by CoffeeScript 1.3.1
var app, get, ready, render, view, _ref;
_ref = app = require('./index'), get = _ref.get, ready = _ref.ready, view = _ref.view;
render = require('./shared').render;
view.fn('unspace', function(s) {
return s && s.replace(/\s/g, '');
});
view.fn('capitalize', function(s) {
return s && s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();
});
get('/', function(page, model) {
return model.subscribe('home', function(err, home) {
home.setNull('titleColor', 'black');
home.setNull('colors', [
{
name: 'black'
}, {
name: 'deep pink'
}, {
name: 'lime green'
}, {
name: 'coral'
}, {
name: 'dark turquoise'
}, {
name: 'dark orchid'
}
]);
return render(page, 'home');
});
});
ready(function(model) {
var colors, home, titleColor;
home = model.at('home');
colors = home.at('colors');
titleColor = home.at('titleColor');
titleColor.on('pre:set', function(value, previous, isLocal, e) {
var titleSelect;
titleSelect = document.getElementById('titleSelect');
if (e && e.target.id === 'titleInput') {
return colors.at(titleSelect.selectedIndex).set('name', value);
}
});
colors.on('pre:set', '*.name', function(index, value, previous, isLocal, e) {
var titleSelect;
titleSelect = document.getElementById('titleSelect');
if (e && e.target.className === 'colorInput' && parseInt(index) === titleSelect.selectedIndex) {
return titleColor.set(value);
}
});
return app.home = {
select: function(e, el) {
return titleColor.set(model.at(el).get('name'));
}
};
});

53
node_modules/derby-examples/sink/lib/app/index.js generated vendored Normal file
View File

@@ -0,0 +1,53 @@
// Generated by CoffeeScript 1.3.1
var app, get, ready, render, _ref;
_ref = app = require('derby').createApp(module), get = _ref.get, ready = _ref.ready;
render = require('./shared').render;
require('./home');
require('./live-css');
require('./table');
require('./leaderboard');
require('./bindings-bench');
['get', 'post', 'put', 'del'].forEach(function(method) {
return app[method]('/submit', function(page, model, _arg) {
var args, body, query;
body = _arg.body, query = _arg.query;
args = JSON.stringify({
method: method,
body: body,
query: query
}, null, ' ');
return render(page, 'submit', {
args: args
});
});
});
get('/error', function() {
throw new Error(500);
});
get('/back', function(page) {
return page.redirect('back');
});
ready(function(model) {
model.set('_showReconnect', true);
exports.connect = function() {
model.set('_showReconnect', false);
setTimeout((function() {
return model.set('_showReconnect', true);
}), 1000);
return model.socket.socket.connect();
};
return exports.reload = function() {
return window.location.reload();
};
});

View File

@@ -0,0 +1,87 @@
// Generated by CoffeeScript 1.3.1
var addPlayer, app, get, randomScore, ready, render, view, _ref;
_ref = app = require('./index'), get = _ref.get, ready = _ref.ready, view = _ref.view;
render = require('./shared').render;
randomScore = function() {
return Math.floor(Math.random() * 20) * 5;
};
addPlayer = function(players, name) {
var id;
id = players.id();
return players.set(id, {
id: id,
name: name,
score: randomScore()
});
};
get('/leaderboard', function(page, model) {
return model.subscribe('leaderboard', function(err, leaderboard) {
var name, players, _i, _len, _ref1;
players = leaderboard.at('players');
if (!players.get()) {
_ref1 = ['Parker Blue', 'Kelly Green', 'Winston Fairbanks'];
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
name = _ref1[_i];
addPlayer(players, name);
}
}
leaderboard.fn('_list', players, function(items) {
var id, item, out;
out = [];
for (id in items) {
item = items[id];
if (item != null ? item.id : void 0) {
out.push(item);
}
}
return out.sort(function(a, b) {
return (b.score - a.score) || (b.id > a.id);
});
});
model.ref(leaderboard.at('_selected'), players, leaderboard.at('_selectedId'));
return render(page, 'leaderboard');
});
});
ready(function(model) {
var leaderboard, newPlayer, players, selected, selectedId;
leaderboard = model.at('leaderboard');
players = leaderboard.at('players');
newPlayer = leaderboard.at('_newPlayer');
selectedId = leaderboard.at('_selectedId');
selected = leaderboard.at('_selected');
return app.leaderboard = {
add: function() {
var name;
if (!(name = newPlayer.get())) {
return;
}
addPlayer(players, name);
return newPlayer.set('');
},
remove: function() {
var id;
id = selected.get('id');
return players.del(id);
},
incr: function() {
return selected.incr('score', 5);
},
decr: function() {
return selected.incr('score', -5);
},
select: function(e, el) {
var id;
id = model.at(el).get('id');
return selectedId.set(id);
},
deselect: function() {
return selectedId.set(null);
}
};
});

72
node_modules/derby-examples/sink/lib/app/live-css.js generated vendored Normal file
View File

@@ -0,0 +1,72 @@
// Generated by CoffeeScript 1.3.1
var app, cssProperty, get, ready, render, view, _ref;
_ref = app = require('./index'), get = _ref.get, ready = _ref.ready, view = _ref.view;
render = require('./shared').render;
view.fn('cssProperty', cssProperty = function(style) {
if (style.active) {
return "" + (style.prop || '') + ": " + (style.value || '') + ";";
} else {
return '';
}
});
get('/live-css', function(page, model) {
return model.subscribe('liveCss', function(err, liveCss) {
liveCss.setNull({
styles: [
{
prop: 'color',
value: '#c00',
active: true
}, {
prop: 'font-weight',
value: 'bold',
active: true
}, {
prop: 'font-size',
value: '18px',
active: false
}
],
outputText: 'Edit this text...'
});
model.fn('_hasActiveStyles', 'liveCss.styles', function(styles) {
var style, _i, _len;
for (_i = 0, _len = styles.length; _i < _len; _i++) {
style = styles[_i];
if (style.active) {
return true;
}
}
return false;
});
model.del('_poppedOut');
return render(page, 'liveCss');
});
});
get({
from: '/live-css',
to: '/live-css/popout'
}, {
forward: function(model) {
return model.set('_poppedOut', true);
},
back: function(model) {
return model.del('_poppedOut');
}
});
ready(function(model) {
return app.liveCss = {
addStyle: function() {
return model.push('liveCss.styles', {});
},
deleteStyle: function(e, el) {
return model.at(el).remove();
}
};
});

58
node_modules/derby-examples/sink/lib/app/shared.js generated vendored Normal file
View File

@@ -0,0 +1,58 @@
// Generated by CoffeeScript 1.3.1
var pages;
pages = [
{
name: 'home',
text: 'Home',
url: '/'
}, {
name: 'liveCss',
text: 'Live CSS',
url: '/live-css'
}, {
name: 'tableEditor',
text: 'Table editor',
url: '/table'
}, {
name: 'leaderboard',
text: 'Leaderboard',
url: '/leaderboard'
}, {
name: 'bindingsBench',
text: 'Bindings benchmark',
url: '/bindings-bench'
}, {
name: 'submit',
text: 'Submit form',
url: '/submit'
}, {
name: 'back',
text: 'Back redirect',
url: '/back'
}, {
name: 'error',
text: 'Error test',
url: '/error'
}
];
exports.render = function(page, name, ctx) {
var i, item, _i, _len;
if (ctx == null) {
ctx = {};
}
ctx.currentPage = name;
ctx.pages = [];
for (i = _i = 0, _len = pages.length; _i < _len; i = ++_i) {
item = pages[i];
item = Object.create(item);
ctx.pages[i] = item;
if (item.name === name) {
item.current = true;
ctx.title = item.text;
}
}
item.isLast = true;
return page.render(name, ctx);
};

View File

@@ -0,0 +1,191 @@
// Generated by CoffeeScript 1.3.1
var breakLeft, breakTop, cloneCol, cloneRow, dragStart, dragging, endDragging, finishCol, finishRow, onColMove, onMove, onRowMove, setLeft, setTop, targetIndex;
dragging = null;
onRowMove = onColMove = function() {};
exports.init = function(app, exported, options) {
var addListener;
addListener = app.view.dom.addListener;
addListener(document, 'mousemove', onMove);
addListener(document, 'mouseup', function() {
return endDragging();
});
addListener(window, 'blur', function() {
return endDragging(true);
});
onRowMove = options.onRowMove, onColMove = options.onColMove;
exported.rowDown = function(e) {
return dragStart(e, cloneRow, setTop, breakTop, '.row', finishRow, e.target.parentNode);
};
return exported.colDown = function(e) {
return dragStart(e, cloneCol, setLeft, breakLeft, '.col', finishCol, e.target);
};
};
onMove = function(e) {
var breakFn, children, i, last, loc, parent, ref;
if (!dragging) {
return;
}
parent = dragging.parent, last = dragging.last, breakFn = dragging.breakFn;
loc = dragging.setFn(e);
i = 0;
children = parent.querySelectorAll(dragging.selector);
while (loc > breakFn(i < last ? children[i] : children[i + 1])) {
i++;
}
if (i !== last) {
if (!(ref = children[i < last ? i : i + 1])) {
ref = children[children.length - 1].nextSibling;
}
parent.insertBefore(dragging.clone, ref);
}
return dragging.last = i;
};
endDragging = function(cancel) {
if (!dragging) {
return;
}
dragging.finish(cancel);
document.body.removeChild(dragging.container);
return dragging = null;
};
targetIndex = function(el) {
var child, i, _i, _len, _ref;
_ref = el.parentNode.childNodes;
for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
child = _ref[i];
if (child === el) {
return i;
}
}
};
dragStart = function(e, cloneFn, setFn, breakFn, selector, finish, el) {
var clone, container, index, nodeOffset, offsetLeft, offsetTop, parent, rect;
if (e.button !== 0) {
return;
}
if (typeof e.preventDefault === "function") {
e.preventDefault();
}
container = document.createElement('table');
container.style.position = 'absolute';
parent = el.parentNode;
rect = el.getBoundingClientRect();
nodeOffset = targetIndex(parent.querySelector(selector));
index = targetIndex(el) - nodeOffset;
clone = cloneFn(container, el, rect, parent, nodeOffset, index);
offsetLeft = rect.left - e.clientX;
offsetTop = rect.top - e.clientY;
dragging = {
el: el,
parent: parent,
clone: clone,
nodeOffset: nodeOffset,
index: index,
last: index,
setFn: setFn,
breakFn: breakFn,
selector: selector,
offsetLeft: offsetLeft,
offsetTop: offsetTop,
finish: finish,
container: container
};
setLeft.call(dragging, e);
setTop.call(dragging, e);
return document.body.appendChild(container);
};
setLeft = function(e) {
var loc;
loc = e.clientX;
this.container.style.left = (loc + window.pageXOffset + this.offsetLeft) + 'px';
return loc;
};
setTop = function(e) {
var loc;
loc = e.clientY;
this.container.style.top = (loc + window.pageYOffset + this.offsetTop) + 'px';
return loc;
};
breakLeft = function(el) {
var rect;
return el && (rect = el.getBoundingClientRect(), rect.width / 2 + rect.left);
};
breakTop = function(el) {
var rect;
return el && (rect = el.getBoundingClientRect(), rect.height / 2 + rect.top);
};
cloneRow = function(container, el, rect, parent) {
var child, clone, spacerHtml, _i, _len, _ref;
spacerHtml = '<tr>';
_ref = el.children;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
child = _ref[_i];
spacerHtml += "<td style=width:" + child.offsetWidth + "px;height:0;padding:0>";
}
clone = el.cloneNode(false);
clone.removeAttribute('id');
clone.style.height = rect.height + 'px';
container.innerHTML = clone.innerHTML = spacerHtml;
parent.insertBefore(clone, el);
container.firstChild.appendChild(el);
return clone;
};
cloneCol = function(container, el, rect, parent, nodeOffset, index) {
var clone, cloneRows, i, nodeIndex, row, rows, spacerHtml, _i, _j, _len, _len1;
rows = parent.parentNode.children;
spacerHtml = '';
for (_i = 0, _len = rows.length; _i < _len; _i++) {
row = rows[_i];
spacerHtml += "<tr class=" + row.className + " style=height:" + row.offsetHeight + "px;width:0;padding:0>";
}
container.innerHTML = spacerHtml;
clone = el.cloneNode(false);
clone.removeAttribute('id');
clone.setAttribute('rowspan', rows.length);
clone.style.padding = 0;
clone.style.width = rect.width + 'px';
nodeIndex = index + nodeOffset;
parent.insertBefore(clone, parent.childNodes[nodeIndex + 1]);
cloneRows = container.firstChild.children;
for (i = _j = 0, _len1 = rows.length; _j < _len1; i = ++_j) {
row = rows[i];
cloneRows[i].appendChild(row.childNodes[nodeIndex]);
}
return clone;
};
finishRow = function(cancel) {
this.parent.removeChild(this.clone);
this.parent.insertBefore(dragging.el, this.parent.childNodes[this.index + this.nodeOffset]);
if (!cancel) {
return onRowMove(this.index, this.last);
}
};
finishCol = function(cancel) {
var cloneRows, i, nodeIndex, row, rows, _i, _len;
this.parent.removeChild(this.clone);
rows = this.parent.parentNode.children;
cloneRows = this.container.firstChild.children;
nodeIndex = this.index + this.nodeOffset;
for (i = _i = 0, _len = rows.length; _i < _len; i = ++_i) {
row = rows[i];
row.insertBefore(cloneRows[i].firstChild, row.childNodes[nodeIndex]);
}
if (!cancel) {
return onColMove(this.index, this.last);
}
};

108
node_modules/derby-examples/sink/lib/app/table.js generated vendored Normal file
View File

@@ -0,0 +1,108 @@
// Generated by CoffeeScript 1.3.1
var app, get, ready, render, sortableTable, _ref;
_ref = app = require('./index'), get = _ref.get, ready = _ref.ready;
render = require('./shared').render;
sortableTable = require('./sortableTable');
get('/table', function(page, model) {
return model.subscribe('table', function(err, table) {
table.setNull({
rows: [
{
name: 1,
cells: [{}, {}, {}]
}, {
name: 2,
cells: [{}, {}, {}]
}
],
lastRow: 1,
cols: [
{
name: 'A'
}, {
name: 'B'
}, {
name: 'C'
}
],
lastCol: 2
});
return render(page, 'tableEditor');
});
});
ready(function(model) {
var alpha, cols, rows;
rows = model.at('table.rows');
cols = model.at('table.cols');
app.tableEditor = {
deleteRow: function(e, el) {
return model.at(el).remove();
},
deleteCol: function(e, el) {
var i, row;
i = model.at(el).leaf();
row = rows.get('length');
while (row--) {
rows.remove("" + row + ".cells", i);
}
return cols.remove(i);
},
addRow: function() {
var cells, col, name;
name = model.incr('table.lastRow') + 1;
cells = [];
col = cols.get('length');
while (col--) {
cells.push({});
}
return rows.push({
name: name,
cells: cells
});
},
addCol: function() {
var name, row;
row = rows.get('length');
while (row--) {
rows.push("" + row + ".cells", {});
}
name = alpha(model.incr('table.lastCol'));
return cols.push({
name: name
});
}
};
alpha = function(num, out) {
var mod;
if (out == null) {
out = '';
}
mod = num % 26;
out = String.fromCharCode(65 + mod) + out;
if (num = Math.floor(num / 26)) {
return alpha(num - 1, out);
} else {
return out;
}
};
return sortableTable.init(app, app.tableEditor, {
onRowMove: function(from, to) {
return rows.move(from, to);
},
onColMove: function(from, to) {
var row, _results;
cols.move(from, to);
row = rows.get('length');
_results = [];
while (row--) {
_results.push(rows.move("" + row + ".cells", from, to));
}
return _results;
}
});
});

36
node_modules/derby-examples/sink/lib/server/index.js generated vendored Normal file
View File

@@ -0,0 +1,36 @@
// Generated by CoffeeScript 1.3.1
var ONE_YEAR, app, derby, express, expressApp, gzippo, http, path, publicPath, root, server, serverError;
http = require('http');
path = require('path');
express = require('express');
gzippo = require('gzippo');
derby = require('derby');
app = require('../app');
serverError = require('./serverError');
ONE_YEAR = 1000 * 60 * 60 * 24 * 365;
root = path.dirname(path.dirname(__dirname));
publicPath = path.join(root, 'public');
(expressApp = express()).use(express.favicon()).use(gzippo.staticGzip(publicPath, {
maxAge: ONE_YEAR
})).use(express.compress()).use(express.bodyParser()).use(express.methodOverride()).use(app.router()).use(expressApp.router).use(serverError(root));
module.exports = server = http.createServer(expressApp);
expressApp.all('*', function(req) {
throw "404: " + req.url;
});
app.createStore({
listen: server
});

View File

@@ -0,0 +1,27 @@
// Generated by CoffeeScript 1.3.1
var derby, isProduction;
derby = require('derby');
isProduction = derby.util.isProduction;
module.exports = function(root) {
var staticPages;
staticPages = derby.createStatic(root);
return function(err, req, res, next) {
var message, status;
if (err == null) {
return next();
}
console.log(err.stack ? err.stack : err);
message = err.message || err.toString();
status = parseInt(message);
if (status === 404) {
return staticPages.render('404', res, {
url: req.url
}, 404);
} else {
return res.send((400 <= status && status < 600) ? status : 500);
}
};
};

15
node_modules/derby-examples/sink/package.json generated vendored Normal file
View File

@@ -0,0 +1,15 @@
{
"name": "derby-kitchen-sink-example",
"description": "Demo of Derby features",
"version": "0.0.0",
"main": "./server.js",
"dependencies": {
"derby": "*",
"express": "3.x",
"gzippo": ">=0.1.4"
},
"private": true,
"devDependencies": {
"coffee-script": ">=1.3.1"
}
}

File diff suppressed because one or more lines are too long

1
node_modules/derby-examples/sink/server.js generated vendored Normal file
View File

@@ -0,0 +1 @@
require('derby').run(__dirname + '/lib/server', 3001);

View File

@@ -0,0 +1,94 @@
{get, ready} = app = require './index'
{render} = require './shared'
# Change N to change the number of drawn circles.
N = 100
get '/bindings-bench', (page, model) ->
boxes = []
for i in [0...N]
boxes.push
count: 0
top: 0
left: 0
color: 0
content: 0
i: i
model.set '_boxes', boxes
render page, 'bindingsBench',
modes: ['setProperty', 'setBox', 'setAll']
ready (model) ->
boxes = model.at '_boxes'
tickProperty = (box) ->
count = box.incr 'count'
box.set 'top', Math.sin(count / 10) * 10
box.set 'left', Math.cos(count / 10) * 10
box.set 'color', count % 255
box.set 'content', count % 100
setProperty = ->
for i in [0...N]
tickProperty boxes.at(i)
return
tickBox = (box, i) ->
count = box.get('count') + 1
box.set
count: count
top: Math.sin(count / 10) * 10
left: Math.cos(count / 10) * 10
color: count % 255
content: count % 100
i: i
setBox = ->
for i in [0...N]
tickBox boxes.at(i), i
return
boxValue = (box, i) ->
count = box.count + 1
return {
count: count
top: Math.sin(count / 10) * 10
left: Math.cos(count / 10) * 10
color: count % 255
content: count % 100
i: i
}
setAll = ->
previous = boxes.get()
value = []
for box, i in previous
value.push boxValue(box, i)
boxes.set value
frames = 0
start = fn = timeout = null
run = ->
fn()
if frames++ == 20
fps = frames * 1000 / (new Date - start)
model.set '_fps', fps.toFixed(1)
frames = 0
start = +new Date
timeout = setTimeout run, 0
modes =
setProperty: setProperty
setBox: setBox
setAll: setAll
app.start = (e, el) ->
clearTimeout timeout
mode = el.innerHTML
model.set '_bindProperties', mode is 'setProperty'
model.set '_mode', mode
fn = modes[mode]
frames = 0
start = +new Date
run()
app.stop = ->
clearTimeout timeout

49
node_modules/derby-examples/sink/src/app/home.coffee generated vendored Normal file
View File

@@ -0,0 +1,49 @@
{get, ready, view} = app = require './index'
{render} = require './shared'
# Define a view helper functions for use in templates
view.fn 'unspace', (s) ->
s && s.replace /\s/g, ''
view.fn 'capitalize', (s) ->
s && s.charAt(0).toUpperCase() + s.slice(1).toLowerCase()
get '/', (page, model) ->
model.subscribe 'home', (err, home) ->
home.setNull 'titleColor', 'black'
home.setNull 'colors', [
{name: 'black'}
{name: 'deep pink'}
{name: 'lime green'}
{name: 'coral'}
{name: 'dark turquoise'}
{name: 'dark orchid'}
]
render page, 'home'
ready (model) ->
home = model.at 'home'
colors = home.at 'colors'
titleColor = home.at 'titleColor'
# DOM bindings pass in the event object as the last argument
# when they set a value in the model
# Set the color of the currently selected option when updating
# the titleColor to keep that option selected
titleColor.on 'pre:set', (value, previous, isLocal, e) ->
titleSelect = document.getElementById 'titleSelect'
if e && e.target.id == 'titleInput'
colors.at(titleSelect.selectedIndex).set 'name', value
# Set the color of the title when updating an option if the
# option is currently selected
colors.on 'pre:set', '*.name', (index, value, previous, isLocal, e) ->
titleSelect = document.getElementById 'titleSelect'
if e && e.target.className == 'colorInput' && parseInt(index) == titleSelect.selectedIndex
titleColor.set value
app.home =
select: (e, el) ->
titleColor.set model.at(el).get('name')

29
node_modules/derby-examples/sink/src/app/index.coffee generated vendored Normal file
View File

@@ -0,0 +1,29 @@
{get, ready} = app = require('derby').createApp module
{render} = require './shared'
require './home'
require './live-css'
require './table'
require './leaderboard'
require './bindings-bench'
['get', 'post', 'put', 'del'].forEach (method) ->
app[method] '/submit', (page, model, {body, query}) ->
args = JSON.stringify {method, body, query}, null, ' '
render page, 'submit', {args}
get '/error', ->
throw new Error 500
get '/back', (page) ->
page.redirect 'back'
ready (model) ->
model.set '_showReconnect', true
exports.connect = ->
# Hide the reconnect link for a second after clicking it
model.set '_showReconnect', false
setTimeout (-> model.set '_showReconnect', true), 1000
model.socket.socket.connect()
exports.reload = -> window.location.reload()

View File

@@ -0,0 +1,52 @@
{get, ready, view} = app = require './index'
{render} = require './shared'
randomScore = -> Math.floor(Math.random() * 20) * 5
addPlayer = (players, name) ->
id = players.id()
players.set id, {id, name, score: randomScore()}
get '/leaderboard', (page, model) ->
model.subscribe 'leaderboard', (err, leaderboard) ->
players = leaderboard.at 'players'
unless players.get()
for name in ['Parker Blue', 'Kelly Green', 'Winston Fairbanks']
addPlayer players, name
# Create list of players sorted in descending order by score
leaderboard.fn '_list', players, (items) ->
out = []
for id, item of items
out.push item if item?.id
return out.sort (a, b) ->
(b.score - a.score) || (b.id > a.id)
model.ref leaderboard.at('_selected'), players, leaderboard.at('_selectedId')
render page, 'leaderboard'
ready (model) ->
leaderboard = model.at 'leaderboard'
players = leaderboard.at 'players'
newPlayer = leaderboard.at '_newPlayer'
selectedId = leaderboard.at '_selectedId'
selected = leaderboard.at '_selected'
app.leaderboard =
add: ->
return unless name = newPlayer.get()
addPlayer players, name
newPlayer.set ''
remove: ->
id = selected.get 'id'
players.del id
incr: -> selected.incr 'score', 5
decr: -> selected.incr 'score', -5
select: (e, el) ->
id = model.at(el).get 'id'
selectedId.set id
deselect: ->
selectedId.set null

View File

@@ -0,0 +1,40 @@
{get, ready, view} = app = require './index'
{render} = require './shared'
view.fn 'cssProperty', cssProperty = (style) ->
if style.active then "#{style.prop || ''}: #{style.value || ''};" else ''
get '/live-css', (page, model) ->
model.subscribe 'liveCss', (err, liveCss) ->
liveCss.setNull
styles: [
{prop: 'color', value: '#c00', active: true}
{prop: 'font-weight', value: 'bold', active: true}
{prop: 'font-size', value: '18px', active: false}
]
outputText: 'Edit this text...'
model.fn '_hasActiveStyles', 'liveCss.styles', (styles) ->
for style in styles
return true if style.active
return false
model.del '_poppedOut'
render page, 'liveCss'
# This is a transition route, which defines how to apply an update
# without re-rendering the entire page. Note that going directly to
# '/live-css/popout' will first call the route above and then call
# the forward route below before rendering
get from: '/live-css', to: '/live-css/popout',
forward: (model) ->
model.set '_poppedOut', true
back: (model) ->
model.del '_poppedOut'
ready (model) ->
app.liveCss =
addStyle: ->
model.push 'liveCss.styles', {}
deleteStyle: (e, el) ->
model.at(el).remove()

22
node_modules/derby-examples/sink/src/app/shared.coffee generated vendored Normal file
View File

@@ -0,0 +1,22 @@
pages = [
{name: 'home', text: 'Home', url: '/'}
{name: 'liveCss', text: 'Live CSS', url: '/live-css'}
{name: 'tableEditor', text: 'Table editor', url: '/table'}
{name: 'leaderboard', text: 'Leaderboard', url: '/leaderboard'}
{name: 'bindingsBench', text: 'Bindings benchmark', url: '/bindings-bench'}
{name: 'submit', text: 'Submit form', url: '/submit'}
{name: 'back', text: 'Back redirect', url: '/back'}
{name: 'error', text: 'Error test', url: '/error'}
]
exports.render = (page, name, ctx = {}) ->
ctx.currentPage = name
ctx.pages = []
for item, i in pages
item = Object.create item
ctx.pages[i] = item
if item.name is name
item.current = true
ctx.title = item.text
item.isLast = true
page.render name, ctx

View File

@@ -0,0 +1,125 @@
dragging = null
onRowMove = onColMove = ->
exports.init = (app, exported, options) ->
{addListener} = app.view.dom
addListener document, 'mousemove', onMove
addListener document, 'mouseup', -> endDragging()
addListener window, 'blur', -> endDragging(true)
{onRowMove, onColMove} = options
exported.rowDown = (e) ->
dragStart e, cloneRow, setTop, breakTop, '.row', finishRow, e.target.parentNode
exported.colDown = (e) ->
dragStart e, cloneCol, setLeft, breakLeft, '.col', finishCol, e.target
onMove = (e) ->
return unless dragging
{parent, last, breakFn} = dragging
loc = dragging.setFn e
i = 0
children = parent.querySelectorAll dragging.selector
i++ while loc > breakFn(
if i < last then children[i] else children[i + 1]
)
unless i == last
unless ref = children[if i < last then i else i + 1]
ref = children[children.length - 1].nextSibling
parent.insertBefore dragging.clone, ref
dragging.last = i
endDragging = (cancel) ->
return unless dragging
dragging.finish cancel
document.body.removeChild dragging.container
dragging = null
targetIndex = (el) ->
for child, i in el.parentNode.childNodes
return i if child == el
dragStart = (e, cloneFn, setFn, breakFn, selector, finish, el) ->
return if e.button != 0
e.preventDefault?()
container = document.createElement 'table'
container.style.position = 'absolute'
parent = el.parentNode
rect = el.getBoundingClientRect()
nodeOffset = targetIndex(parent.querySelector selector)
index = targetIndex(el) - nodeOffset
clone = cloneFn container, el, rect, parent, nodeOffset, index
offsetLeft = rect.left - e.clientX
offsetTop = rect.top - e.clientY
dragging = {el, parent, clone, nodeOffset, index, last: index, setFn, breakFn, selector, offsetLeft, offsetTop, finish, container}
setLeft.call dragging, e
setTop.call dragging, e
document.body.appendChild container
setLeft = (e) ->
loc = e.clientX
@container.style.left = (loc + window.pageXOffset + @offsetLeft) + 'px'
return loc
setTop = (e) ->
loc = e.clientY
@container.style.top = (loc + window.pageYOffset + @offsetTop) + 'px'
return loc
breakLeft = (el) -> el && (
rect = el.getBoundingClientRect()
rect.width / 2 + rect.left
)
breakTop = (el) -> el && (
rect = el.getBoundingClientRect()
rect.height / 2 + rect.top
)
cloneRow = (container, el, rect, parent) ->
spacerHtml = '<tr>'
for child in el.children
spacerHtml += "<td style=width:#{child.offsetWidth}px;height:0;padding:0>"
clone = el.cloneNode(false)
clone.removeAttribute 'id'
clone.style.height = rect.height + 'px'
container.innerHTML = clone.innerHTML = spacerHtml
parent.insertBefore clone, el
container.firstChild.appendChild el
return clone
cloneCol = (container, el, rect, parent, nodeOffset, index) ->
rows = parent.parentNode.children
spacerHtml = ''
for row in rows
spacerHtml += "<tr class=#{row.className} style=height:#{row.offsetHeight}px;width:0;padding:0>"
container.innerHTML = spacerHtml
clone = el.cloneNode(false)
clone.removeAttribute 'id'
clone.setAttribute 'rowspan', rows.length
clone.style.padding = 0
clone.style.width = rect.width + 'px'
nodeIndex = index + nodeOffset
parent.insertBefore clone, parent.childNodes[nodeIndex + 1]
cloneRows = container.firstChild.children
for row, i in rows
cloneRows[i].appendChild row.childNodes[nodeIndex]
return clone
finishRow = (cancel) ->
# Put things back where they started
@parent.removeChild @clone
@parent.insertBefore dragging.el, @parent.childNodes[@index + @nodeOffset]
# Actually do the move
onRowMove @index, @last unless cancel
finishCol = (cancel) ->
# Put things back where they started
@parent.removeChild @clone
rows = @parent.parentNode.children
cloneRows = @container.firstChild.children
nodeIndex = @index + @nodeOffset
for row, i in rows
row.insertBefore cloneRows[i].firstChild, row.childNodes[nodeIndex]
# Actually do the move
onColMove @index, @last unless cancel

70
node_modules/derby-examples/sink/src/app/table.coffee generated vendored Normal file
View File

@@ -0,0 +1,70 @@
{get, ready} = app = require './index'
{render} = require './shared'
sortableTable = require './sortableTable'
get '/table', (page, model) ->
model.subscribe 'table', (err, table) ->
table.setNull
rows: [
{name: 1, cells: [{}, {}, {}]}
{name: 2, cells: [{}, {}, {}]}
]
lastRow: 1
cols: [
{name: 'A'}
{name: 'B'}
{name: 'C'}
]
lastCol: 2
render page, 'tableEditor'
ready (model) ->
rows = model.at 'table.rows'
cols = model.at 'table.cols'
app.tableEditor =
deleteRow: (e, el) ->
model.at(el).remove()
deleteCol: (e, el) ->
# TODO: Make these move operations atomic when Racer has atomic support
i = model.at(el).leaf()
row = rows.get 'length'
while row--
rows.remove "#{row}.cells", i
cols.remove i
addRow: ->
name = model.incr('table.lastRow') + 1
cells = []
col = cols.get 'length'
while col--
cells.push {}
rows.push {name, cells}
addCol: ->
row = rows.get 'length'
while row--
rows.push "#{row}.cells", {}
name = alpha model.incr 'table.lastCol'
cols.push {name}
alpha = (num, out = '') ->
mod = num % 26
out = String.fromCharCode(65 + mod) + out
if num = Math.floor num / 26
return alpha num - 1, out
else
return out
sortableTable.init app, app.tableEditor,
onRowMove: (from, to) ->
rows.move from, to
onColMove: (from, to) ->
# TODO: Make these move operations atomic when Racer has atomic support
cols.move from, to
row = rows.get 'length'
while row--
rows.move "#{row}.cells", from, to

View File

@@ -0,0 +1,50 @@
http = require 'http'
path = require 'path'
express = require 'express'
gzippo = require 'gzippo'
derby = require 'derby'
app = require '../app'
serverError = require './serverError'
## SERVER CONFIGURATION ##
ONE_YEAR = 1000 * 60 * 60 * 24 * 365
root = path.dirname path.dirname __dirname
publicPath = path.join root, 'public'
(expressApp = express())
.use(express.favicon())
# Gzip static files and serve from memory
.use(gzippo.staticGzip publicPath, maxAge: ONE_YEAR)
# Gzip dynamically rendered content
.use(express.compress())
# Uncomment to add form data parsing support
.use(express.bodyParser())
.use(express.methodOverride())
# Uncomment and supply secret to add Derby session handling
# Derby session middleware creates req.model and subscribes to _session
# .use(express.cookieParser 'secret_sauce')
# .use(express.session cookie: {maxAge: ONE_YEAR})
# .use(app.session())
# The router method creates an express middleware from the app's routes
.use(app.router())
.use(expressApp.router)
.use(serverError root)
module.exports = server = http.createServer expressApp
## SERVER ONLY ROUTES ##
expressApp.all '*', (req) ->
throw "404: #{req.url}"
## STORE SETUP ##
app.createStore listen: server

View File

@@ -0,0 +1,18 @@
derby = require 'derby'
{isProduction} = derby.util
module.exports = (root) ->
staticPages = derby.createStatic root
return (err, req, res, next) ->
return next() unless err?
console.log(if err.stack then err.stack else err)
## Customize error handling here ##
message = err.message || err.toString()
status = parseInt message
if status is 404
staticPages.render '404', res, {url: req.url}, 404
else
res.send if 400 <= status < 600 then status else 500

1
node_modules/derby-examples/sink/styles/404.styl generated vendored Normal file
View File

@@ -0,0 +1 @@
@import "./base";

153
node_modules/derby-examples/sink/styles/app/index.styl generated vendored Normal file
View File

@@ -0,0 +1,153 @@
@import "nib/vendor";
p {
margin: 0;
padding: 0;
}
body {
margin: 10px;
}
body,
select {
font: 13px/normal arial,sans-serif;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
#alert {
position: absolute;
text-align: center;
top: 0;
left: 0;
width: 100%;
height: 0;
z-index: 99;
}
#alert > p {
background: #fff1a8;
border: 1px solid #999;
border-top: 0;
border-radius: 0 0 3px 3px;
display: inline-block;
line-height: 21px;
padding: 0 12px;
}
.css {
list-style: none;
padding-left: 1em;
margin: 0
}
.cssOutput {
border: 1px solid rgba(black, 0);
background: rgba(white, 0);
}
.popupTitle {
display: none;
}
.poppedOut {
position: fixed;
border: 1px solid rgba(black, .2);
box-shadow: 0 1px 8px rgba(black, .2), 0 16px 32px rgba(black, .2);
top: 45px;
bottom: 1em;
left: 50%;
right: 1em;
background: rgba(white, .8);
transition-property: border, box-shadow;
transition-duration: .5s;
transition-timing-function: ease-out;
.popupTitle {
display: block;
padding: .5em 1em;
text-align: right;
background: #f3f3f3;
border-bottom: 1px solid #e7e7e7;
}
.popupContent {
padding: 1em;
}
}
.tableEditor {
table {
user-select: none;
}
th {
cursor: move;
padding: 0 4px;
}
.foot {
text-align: center;
}
}
#leaderboard {
green = #9acd05
pink = #fe5cba
font-size: 2em;
font-family: "Helvetica Neue";
font-weight: 300;
display: inline-block;
button {
font-size: 13px;
}
.selectedPlayer {
font-weight: 500;
margin: 1em 0;
padding-bottom: 5px;
border-bottom: 5px solid green;
button {
vertical-align: 5px;
}
}
.vote {
float: right;
}
ul {
list-style: none;
padding: 0;
margin-top: 5px;
cursor: pointer;
li {
padding: 5px;
width: 400px;
}
li:hover {
background: lighten(pink, 80%);
}
.score {
font-weight: 500;
float: right;
}
.selected,
.selected:hover {
background: pink;
box-shadow: inset 0 -2px darken(pink, 50%);
}
}
}
.bindingsBench p {
margin-bottom: 1em;
}
.box {
border-radius: 100px;
width: 20px;
height: 10px;
padding: 5px 0;
color: #ccc;
font: 10px/10px Arial;
text-align: center;
position: absolute;
}
.box-view {
width: 20px;
height: 20px;
float: left;
position: relative;
margin: 8px;
}

16
node_modules/derby-examples/sink/styles/base.styl generated vendored Normal file
View File

@@ -0,0 +1,16 @@
@import "./reset";
@import "nib/vendor";
body {
padding: 2em;
}
h1 {
font-size: 2em;
margin-bottom: .5em;
}
p {
line-height: 2em;
}
* {
box-sizing: border-box
}

21
node_modules/derby-examples/sink/styles/reset.styl generated vendored Normal file
View File

@@ -0,0 +1,21 @@
body,h1,h2,h3,h4,th {
font: 13px/normal Arial,sans-serif;
}
body {
background: #fff;
color: #000;
}
body,fieldset,form,h1,h2,h3,h4,li,ol,p,td,th,ul {
margin: 0;
padding: 0;
}
ul {
margin: 0 normal;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
fieldset,img {
border: 0;
}

16
node_modules/derby-examples/sink/views/404.html generated vendored Normal file
View File

@@ -0,0 +1,16 @@
<!--
This is a static template file, so it doesn't have an associated app.
It is rendered by the server via a staticPages renderer.
Since static pages don't include the Derby client library, they can't have
bound variables that automatically update. However, they do support initial
template tag rendering from a context object and/or model.
-->
<Title:>
Not found
<Body:>
<h1>404</h1>
<p>Sorry, we can't find anything at <b>{{url}}</b>.
<p>Try heading back to the <a href="/">home page</a>.

View File

@@ -0,0 +1,37 @@
<Body:>
<div>
<p>
{#if _mode}
Mode: <b>{_mode}</b> &nbsp; FPS: <b>{_fps}</b>
{else}
Select a mode to run:
{/}
</p>
<p>
{{#each modes}}<button x-bind="click: start">{{this}}</button>{{/}}
<button x-bind="click: stop">Stop</button>
</p>
</div>
{#if _bindProperties}
<div>
{#each _boxes}
<div class="box-view">
<div id="box-{{i}}" class="box" style="top: {.top}px; left: {.left}px; background: rgb(0, 0, {.color});">
{.content}
</div>
</div>
{/}
</div>
{else}
<div>
{#each _boxes}
<div class="box-view">
<div id="box-{{i}}" class="box" style="top: {{top}}px; left: {{left}}px; background: rgb(0, 0, {{color}});">
{{content}}
</div>
</div>
{/}
</div>
{/}

32
node_modules/derby-examples/sink/views/app/home.html generated vendored Normal file
View File

@@ -0,0 +1,32 @@
<Body:>
{{#with home}}
<h1 style="color:{unspace(.titleColor)}">Welcome in {.titleColor}!</h1>
<p>This is a collection of random demos. Check 'em out!</p><br>
<p>
<label>Title color:
<select id=titleSelect>
{#each .colors}
<option selected="{equal(.name, home.titleColor)}">{capitalize(.name)}</option>
{/}
</select>
</label>
<input id=titleInput value={.titleColor}>
<h3>Colors:</h3>
<div>
{#each .colors}
<p>
<input type=radio name=titleRadio checked="{equal(.name, home.titleColor)}">
<input class=colorInput value={.name}>
<button x-bind="click: home.select">Select</button>
</p>
{/}
</div>
</p><br><br>
<p><a href=#jump>Test jump link</a></p><br>
<p><a href=/live-css/popout>Test Live CSS popped out</a></p>
<p style="margin:400px 0 1000px">
<span id=jump>Jumped!</span> -
<a href="#">Back to top</a> -
<a href=/live-css>Go to Live CSS</a>
</p>
{{/}}

33
node_modules/derby-examples/sink/views/app/index.html generated vendored Normal file
View File

@@ -0,0 +1,33 @@
<import: src=shared>
<import: src=home>
<import: src=liveCss>
<import: src=tableEditor>
<import: src=leaderboard>
<import: src=submit>
<import: src=bindingsBench>
<Title:>
Derby demo: {{title}}
<Header:>
<body class={{currentPage}}>
<!-- components are void by default, and should not have a closing tag -->
<app:shared:alert>
<!-- if a component is nonvoid, it must have a closing tag -->
<app:nav>
{{#each pages}}
{{#if current}}
<b>{{text}}</b>
{{else}}
<a href={{url}}>{{text}}</a>
{{/}}
{{#unless isLast}} | {{/}}
{{/}}
</app:nav>
<nav: nonvoid>
<nav>
<!-- nonvoid components support a special `content` macro -->
{{{content}}}
<hr>
</nav>

View File

@@ -0,0 +1,44 @@
<Root:>
<html x-bind="click: leaderboard.deselect">
<Body:>
{{#with leaderboard}}
<form x-bind="submit: leaderboard.add">
<input value={._newPlayer}> <input type=submit value="Add player">
<button x-bind="click: leaderboard.remove" disabled={not(._selected)}>
Remove
{#if ._selected}
{.name}
{else}
selected
{/}
</button>
</form>
<!--
By binding click here, it will prevent click events within this div
from bubbling further and reaching the document node. All clicks
outside of this div will continue bubbling up to the document.
-->
<div id=leaderboard x-bind=click>
<div class=selectedPlayer>
{#if ._selected}
<p class=vote>
<button x-bind="click: leaderboard.incr">+ 5</button>
<button x-bind="click: leaderboard.decr">- 5</button>
</p>
<span>{.name}</span>
{else}
Click a player to select
{/}
</div>
<ul>
{#each ._list}
<li class="{#if equal(.id, leaderboard._selectedId)}selected{/}"
x-bind="click: leaderboard.select">
<p class=score>{.score}</p>{{name}}
</li>
{/}
</ul>
</div>
{{/}}

View File

@@ -0,0 +1,44 @@
<Body:>
<select multiple>
<optgroup label="CSS properties">
{#each liveCss.styles}<option selected={.active}>{.prop}</option>{/}
</optgroup>
</select>
<div>
{#each liveCss.styles}
<p>
<input type="checkbox" checked="{.active}">
<input value="{.prop}" disabled="{not(.active)}">
<input value="{.value}" disabled="{not(.active)}">
<button x-bind="click: liveCss.deleteStyle">Delete</button>
</p>
{/}
</div>
<button x-bind="click: liveCss.addStyle">Add</button>
<h3>Currently applied:</h3>
<div>
{#if _hasActiveStyles}
<p>&#123;</p>
<ul class=css>
{#each liveCss.styles}
<li>{cssProperty(this)}</li>
{/}
</ul>
<p>}</p>
{else}
(None)
{/}
</div>
<div>
{#unless _poppedOut}
<h3 style=display:inline-block>Output:</h3> &nbsp; <a href="/live-css/popout">Pop out</a>
{/}
</div>
<div class="{#if _poppedOut}poppedOut{/} cssOutput">
<p class=popupTitle><a href="/live-css">Close</a></p>
<div class=popupContent>
<p style="{#each liveCss.styles}{cssProperty(this)}{/}" contenteditable>
{unescaped liveCss.outputText}
</p>
</div>
</div>

14
node_modules/derby-examples/sink/views/app/shared.html generated vendored Normal file
View File

@@ -0,0 +1,14 @@
<alert:>
<div id=alert>
{#unless connected}
<p>
{#if canConnect}
<!-- Leading space is removed, and trailing space is maintained -->
Offline
{#if _showReconnect}&ndash; <a x-bind=click:connect>Reconnect</a>{/}
{else}
Unable to reconnect &ndash; <a x-bind=click:reload>Reload</a>
{/}
</p>
{/}
</div>

View File

@@ -0,0 +1,9 @@
<Body:>
<form action=submit method=post>
<input type=hidden name=_method value=put>
<p><label>Name: <input type=text name=user[name]></label></p>
<p><label>Email: <input type=text name=user[email]></label></p>
<p><input type=submit></p>
</form>
<h3>Arguments:</h3>
<pre><code>{{args}}</code></pre>

View File

@@ -0,0 +1,25 @@
<Body:>
<button x-bind="click: tableEditor.addRow">Add row</button>
<button x-bind="click: tableEditor.addCol">Add column</button>
<hr>
<table>
<tr>
<td></td>
{#each table.cols}
<th x-bind="mousedown: tableEditor.colDown" class=col>{.name}</th>
{/}
<td></td>
</tr>
{#each table.rows}
<tr class=row>
<th x-bind="mousedown: tableEditor.rowDown">{.name}</th>
{#each .cells}<td><input value={.text}></td>{/}
<td><button x-bind="click: tableEditor.deleteRow">Delete</button></td>
</tr>
{/}
<tr class=foot>
<td></td>
{#each table.cols}<td><button x-bind="click: tableEditor.deleteCol">Delete</button></td>{/}
<td></td>
</tr>
</table>