Commit e97e13c5 authored by Arthur Verschaeve's avatar Arthur Verschaeve

Drop `derby` app

The app has been down for multiple years, was left unmaintained for
really long and is outdated in many ways. Thus, we're (temporarily)
removing it. If somebody comes in, volunteers to fix the problems and we
find a place to host it.

We already decided earlier to drop it from the homepage.
Ref 7f59ef71

Fixes gh-546
Fixes gh-593
parent f5fc61c2
{
"directory": "public/components"
}
node_modules
lib
gen
*.swp
*.un~
compile:
npm install
./node_modules/coffee-script/bin/coffee -b -o ./lib -c ./src
run: compile
node server.js
deploy-setup: compile
git init
heroku git:remote -a todomvc-derby
sed -i 's/lib//' .gitignore
git add -A
git commit -m "Deployment update"
deploy:
git push heroku master
{
"name": "todomvc-derby",
"version": "0.0.0",
"dependencies": {
"todomvc-common": "~0.3.0"
}
}
{
"name": "todomvc-derby",
"description": "TodoMVC todo app using Derby",
"version": "0.1.0",
"main": "server.js",
"dependencies": {
"derby": "git://github.com/codeparty/derby#d1ac9c0fcd",
"racer": "git://github.com/codeparty/racer#8d3357582e",
"express": "~3.0.1",
"gzippo": "~0.2.0"
},
"devDependencies": {
"coffee-script": "~1.4.0"
},
"private": true
}
html,
body {
margin: 0;
padding: 0;
}
button {
margin: 0;
padding: 0;
border: 0;
background: none;
font-size: 100%;
vertical-align: baseline;
font-family: inherit;
color: inherit;
-webkit-appearance: none;
-ms-appearance: none;
-o-appearance: none;
appearance: none;
}
body {
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em;
background: #eaeaea url('bg.png');
color: #4d4d4d;
width: 550px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
-ms-font-smoothing: antialiased;
-o-font-smoothing: antialiased;
font-smoothing: antialiased;
}
button,
input[type="checkbox"] {
outline: none;
}
#todoapp {
background: #fff;
background: rgba(255, 255, 255, 0.9);
margin: 130px 0 40px 0;
border: 1px solid #ccc;
position: relative;
border-top-left-radius: 2px;
border-top-right-radius: 2px;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.15);
}
#todoapp:before {
content: '';
border-left: 1px solid #f5d6d6;
border-right: 1px solid #f5d6d6;
width: 2px;
position: absolute;
top: 0;
left: 40px;
height: 100%;
}
#todoapp input::-webkit-input-placeholder {
font-style: italic;
}
#todoapp input::-moz-placeholder {
font-style: italic;
color: #a9a9a9;
}
#todoapp h1 {
position: absolute;
top: -120px;
width: 100%;
font-size: 70px;
font-weight: bold;
text-align: center;
color: #b3b3b3;
color: rgba(255, 255, 255, 0.3);
text-shadow: -1px -1px rgba(0, 0, 0, 0.2);
-webkit-text-rendering: optimizeLegibility;
-moz-text-rendering: optimizeLegibility;
-ms-text-rendering: optimizeLegibility;
-o-text-rendering: optimizeLegibility;
text-rendering: optimizeLegibility;
}
#header {
padding-top: 15px;
border-radius: inherit;
}
#header:before {
content: '';
position: absolute;
top: 0;
right: 0;
left: 0;
height: 15px;
z-index: 2;
border-bottom: 1px solid #6c615c;
background: #8d7d77;
background: -webkit-gradient(linear, left top, left bottom, from(rgba(132, 110, 100, 0.8)),to(rgba(101, 84, 76, 0.8)));
background: -webkit-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
background: linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670');
border-top-left-radius: 1px;
border-top-right-radius: 1px;
}
#new-todo,
.edit {
position: relative;
margin: 0;
width: 100%;
font-size: 24px;
font-family: inherit;
line-height: 1.4em;
border: 0;
outline: none;
color: inherit;
padding: 6px;
border: 1px solid #999;
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
-ms-font-smoothing: antialiased;
-o-font-smoothing: antialiased;
font-smoothing: antialiased;
}
#new-todo {
padding: 16px 16px 16px 60px;
border: none;
background: rgba(0, 0, 0, 0.02);
z-index: 2;
box-shadow: none;
}
#main {
position: relative;
z-index: 2;
border-top: 1px dotted #adadad;
}
label[for='toggle-all'] {
display: none;
}
#toggle-all {
position: absolute;
top: -42px;
left: -4px;
width: 40px;
text-align: center;
/* Mobile Safari */
border: none;
}
#toggle-all:before {
content: '»';
font-size: 28px;
color: #d9d9d9;
padding: 0 25px 7px;
}
#toggle-all:checked:before {
color: #737373;
}
#todo-list {
margin: 0;
padding: 0;
list-style: none;
}
#todo-list li {
position: relative;
font-size: 24px;
border-bottom: 1px dotted #ccc;
}
#todo-list li:last-child {
border-bottom: none;
}
#todo-list li.editing {
border-bottom: none;
padding: 0;
}
#todo-list li.editing .edit {
display: block;
width: 506px;
padding: 13px 17px 12px 17px;
margin: 0 0 0 43px;
}
#todo-list li.editing .view {
display: none;
}
#todo-list li .toggle {
text-align: center;
width: 40px;
/* auto, since non-WebKit browsers doesn't support input styling */
height: auto;
position: absolute;
top: 0;
bottom: 0;
margin: auto 0;
/* Mobile Safari */
border: none;
-webkit-appearance: none;
-ms-appearance: none;
-o-appearance: none;
appearance: none;
}
#todo-list li .toggle:after {
content: '✔';
/* 40 + a couple of pixels visual adjustment */
line-height: 43px;
font-size: 20px;
color: #d9d9d9;
text-shadow: 0 -1px 0 #bfbfbf;
}
#todo-list li .toggle:checked:after {
color: #85ada7;
text-shadow: 0 1px 0 #669991;
bottom: 1px;
position: relative;
}
#todo-list li label {
white-space: pre;
word-break: break-word;
padding: 15px 60px 15px 15px;
margin-left: 45px;
display: block;
line-height: 1.2;
-webkit-transition: color 0.4s;
transition: color 0.4s;
}
#todo-list li.completed label {
color: #a9a9a9;
text-decoration: line-through;
}
#todo-list li .destroy {
display: none;
position: absolute;
top: 0;
right: 10px;
bottom: 0;
width: 40px;
height: 40px;
margin: auto 0;
font-size: 22px;
color: #a88a8a;
-webkit-transition: all 0.2s;
transition: all 0.2s;
}
#todo-list li .destroy:hover {
text-shadow: 0 0 1px #000,
0 0 10px rgba(199, 107, 107, 0.8);
-webkit-transform: scale(1.3);
transform: scale(1.3);
}
#todo-list li .destroy:after {
content: '✖';
}
#todo-list li:hover .destroy {
display: block;
}
#todo-list li .edit {
display: none;
}
#todo-list li.editing:last-child {
margin-bottom: -1px;
}
#footer {
color: #777;
padding: 0 15px;
position: absolute;
right: 0;
bottom: -31px;
left: 0;
height: 20px;
z-index: 1;
text-align: center;
}
#footer:before {
content: '';
position: absolute;
right: 0;
bottom: 31px;
left: 0;
height: 50px;
z-index: -1;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3),
0 6px 0 -3px rgba(255, 255, 255, 0.8),
0 7px 1px -3px rgba(0, 0, 0, 0.3),
0 43px 0 -6px rgba(255, 255, 255, 0.8),
0 44px 2px -6px rgba(0, 0, 0, 0.2);
}
#todo-count {
float: left;
text-align: left;
}
#filters {
margin: 0;
padding: 0;
list-style: none;
position: absolute;
right: 0;
left: 0;
}
#filters li {
display: inline;
}
#filters li a {
color: #83756f;
margin: 2px;
text-decoration: none;
}
#filters li a.selected {
font-weight: bold;
}
#clear-completed {
float: right;
position: relative;
line-height: 20px;
text-decoration: none;
background: rgba(0, 0, 0, 0.1);
font-size: 11px;
padding: 0 10px;
border-radius: 3px;
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.2);
}
#clear-completed:hover {
background: rgba(0, 0, 0, 0.15);
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.3);
}
#info {
margin: 65px auto 0;
color: #a6a6a6;
font-size: 12px;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7);
text-align: center;
}
#info a {
color: inherit;
}
/*
Hack to remove background from Mobile Safari.
Can't use it globally since it destroys checkboxes in Firefox and Opera
*/
@media screen and (-webkit-min-device-pixel-ratio:0) {
#toggle-all,
#todo-list li .toggle {
background: none;
}
#todo-list li .toggle {
height: 40px;
}
#toggle-all {
top: -56px;
left: -15px;
width: 65px;
height: 41px;
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
-webkit-appearance: none;
appearance: none;
}
}
.hidden {
display: none;
}
hr {
margin: 20px 0;
border: 0;
border-top: 1px dashed #C5C5C5;
border-bottom: 1px dashed #F7F7F7;
}
.learn a {
font-weight: normal;
text-decoration: none;
color: #b83f45;
}
.learn a:hover {
text-decoration: underline;
color: #787e7e;
}
.learn h3,
.learn h4,
.learn h5 {
margin: 10px 0;
font-weight: 500;
line-height: 1.2;
color: #000;
}
.learn h3 {
font-size: 24px;
}
.learn h4 {
font-size: 18px;
}
.learn h5 {
margin-bottom: 0;
font-size: 14px;
}
.learn ul {
padding: 0;
margin: 0 0 30px 25px;
}
.learn li {
line-height: 20px;
}
.learn p {
font-size: 15px;
font-weight: 300;
line-height: 1.3;
margin-top: 0;
margin-bottom: 0;
}
.quote {
border: none;
margin: 20px 0 60px 0;
}
.quote p {
font-style: italic;
}
.quote p:before {
content: '“';
font-size: 50px;
opacity: .15;
position: absolute;
top: -20px;
left: 3px;
}
.quote p:after {
content: '”';
font-size: 50px;
opacity: .15;
position: absolute;
bottom: -42px;
right: 3px;
}
.quote footer {
position: absolute;
bottom: -40px;
right: 0;
}
.quote footer img {
border-radius: 3px;
}
.quote footer a {
margin-left: 5px;
vertical-align: middle;
}
.speech-bubble {
position: relative;
padding: 10px;
background: rgba(0, 0, 0, .04);
border-radius: 5px;
}
.speech-bubble:after {
content: '';
position: absolute;
top: 100%;
right: 30px;
border: 13px solid transparent;
border-top-color: rgba(0, 0, 0, .04);
}
.learn-bar > .learn {
position: absolute;
width: 272px;
top: 8px;
left: -300px;
padding: 10px;
border-radius: 5px;
background-color: rgba(255, 255, 255, .6);
-webkit-transition-property: left;
transition-property: left;
-webkit-transition-duration: 500ms;
transition-duration: 500ms;
}
@media (min-width: 899px) {
.learn-bar {
width: auto;
margin: 0 0 0 300px;
}
.learn-bar > .learn {
left: 8px;
}
.learn-bar #todoapp {
width: 550px;
margin: 130px auto 40px auto;
}
}
(function () {
'use strict';
// Underscore's Template Module
// Courtesy of underscorejs.org
var _ = (function (_) {
_.defaults = function (object) {
if (!object) {
return object;
}
for (var argsIndex = 1, argsLength = arguments.length; argsIndex < argsLength; argsIndex++) {
var iterable = arguments[argsIndex];
if (iterable) {
for (var key in iterable) {
if (object[key] == null) {
object[key] = iterable[key];
}
}
}
}
return object;
}
// By default, Underscore uses ERB-style template delimiters, change the
// following template settings to use alternative delimiters.
_.templateSettings = {
evaluate : /<%([\s\S]+?)%>/g,
interpolate : /<%=([\s\S]+?)%>/g,
escape : /<%-([\s\S]+?)%>/g
};
// When customizing `templateSettings`, if you don't want to define an
// interpolation, evaluation or escaping regex, we need one that is
// guaranteed not to match.
var noMatch = /(.)^/;
// Certain characters need to be escaped so that they can be put into a
// string literal.
var escapes = {
"'": "'",
'\\': '\\',
'\r': 'r',
'\n': 'n',
'\t': 't',
'\u2028': 'u2028',
'\u2029': 'u2029'
};
var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
// JavaScript micro-templating, similar to John Resig's implementation.
// Underscore templating handles arbitrary delimiters, preserves whitespace,
// and correctly escapes quotes within interpolated code.
_.template = function(text, data, settings) {
var render;
settings = _.defaults({}, settings, _.templateSettings);
// Combine delimiters into one regular expression via alternation.
var matcher = new RegExp([
(settings.escape || noMatch).source,
(settings.interpolate || noMatch).source,
(settings.evaluate || noMatch).source
].join('|') + '|$', 'g');
// Compile the template source, escaping string literals appropriately.
var index = 0;
var source = "__p+='";
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
source += text.slice(index, offset)
.replace(escaper, function(match) { return '\\' + escapes[match]; });
if (escape) {
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
}
if (interpolate) {
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
}
if (evaluate) {
source += "';\n" + evaluate + "\n__p+='";
}
index = offset + match.length;
return match;
});
source += "';\n";
// If a variable is not specified, place data values in local scope.
if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
source = "var __t,__p='',__j=Array.prototype.join," +
"print=function(){__p+=__j.call(arguments,'');};\n" +
source + "return __p;\n";
try {
render = new Function(settings.variable || 'obj', '_', source);
} catch (e) {
e.source = source;
throw e;
}
if (data) return render(data, _);
var template = function(data) {
return render.call(this, data, _);
};
// Provide the compiled function source as a convenience for precompilation.
template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
return template;
};
return _;
})({});
if (location.hostname === 'todomvc.com') {
window._gaq = [['_setAccount','UA-31081062-1'],['_trackPageview']];(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.src='//www.google-analytics.com/ga.js';s.parentNode.insertBefore(g,s)}(document,'script'));
}
function redirect() {
if (location.hostname === 'tastejs.github.io') {
location.href = location.href.replace('tastejs.github.io/todomvc', 'todomvc.com');
}
}
function findRoot() {
var base = location.href.indexOf('examples/');
return location.href.substr(0, base);
}
function getFile(file, callback) {
if (!location.host) {
return console.info('Miss the info bar? Run TodoMVC from a server to avoid a cross-origin error.');
}
var xhr = new XMLHttpRequest();
xhr.open('GET', findRoot() + file, true);
xhr.send();
xhr.onload = function () {
if (xhr.status === 200 && callback) {
callback(xhr.responseText);
}
};
}
function Learn(learnJSON, config) {
if (!(this instanceof Learn)) {
return new Learn(learnJSON, config);
}
var template, framework;
if (typeof learnJSON !== 'object') {
try {
learnJSON = JSON.parse(learnJSON);
} catch (e) {
return;
}
}
if (config) {
template = config.template;
framework = config.framework;
}
if (!template && learnJSON.templates) {
template = learnJSON.templates.todomvc;
}
if (!framework && document.querySelector('[data-framework]')) {
framework = document.querySelector('[data-framework]').dataset.framework;
}
this.template = template;
if (learnJSON.backend) {
this.frameworkJSON = learnJSON.backend;
this.append({
backend: true
});
} else if (learnJSON[framework]) {
this.frameworkJSON = learnJSON[framework];
this.append();
}
}
Learn.prototype.append = function (opts) {
var aside = document.createElement('aside');
aside.innerHTML = _.template(this.template, this.frameworkJSON);
aside.className = 'learn';
if (opts && opts.backend) {
// Remove demo link
var sourceLinks = aside.querySelector('.source-links');
var heading = sourceLinks.firstElementChild;
var sourceLink = sourceLinks.lastElementChild;
// Correct link path
var href = sourceLink.getAttribute('href');
sourceLink.setAttribute('href', href.substr(href.lastIndexOf('http')));
sourceLinks.innerHTML = heading.outerHTML + sourceLink.outerHTML;
} else {
// Localize demo links
var demoLinks = aside.querySelectorAll('.demo-link');
Array.prototype.forEach.call(demoLinks, function (demoLink) {
if (demoLink.getAttribute('href').substr(0, 4) !== 'http') {
demoLink.setAttribute('href', findRoot() + demoLink.getAttribute('href'));
}
});
}
document.body.className = (document.body.className + ' learn-bar').trim();
document.body.insertAdjacentHTML('afterBegin', aside.outerHTML);
};
redirect();
getFile('learn.json', Learn);
})();
# Derby TodoMVC Example
> MVC framework making it easy to write realtime, collaborative applications that run in both Node.js and browsers.
> _[Derby - derbyjs.com](http://derbyjs.com)_
## Learning Derby
The [Derby website](http://derbyjs.com) is a great resource for getting started.
Here are some links you may find helpful:
* [Introduction](http://derbyjs.com/#introduction)
* [Getting Started](http://derbyjs.com/#getting_started)
* [Applications built with Derby](https://github.com/codeparty/derby/wiki/Community-Projects#website-showcase)
* [Blog](http://blog.derbyjs.com)
* [FAQ](https://github.com/codeparty/derby/wiki/Frequently-Asked-Questions)
* [Derby on GitHub](https://github.com/codeparty/derby)
Articles and guides from the community:
* [Learning DerbyJS](http://nickofnicks.com/2013/04/24/nodejs/derbyjs/learning-derbyjs/)
* [Screencast - 6 Things I'm Loving about DerbyJS](http://micknelson.wordpress.com/2012/07/27/6-things-im-loving-about-derbyjs)
Get help from other Derby users:
* [Derby on StackOverflow](http://stackoverflow.com/questions/tagged/derbyjs)
* [Mailing list on Google Groups](https://groups.google.com/forum/?fromgroups#!forum/derbyjs)
* [Derby on Twitter](http://twitter.com/derbyjs)
_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._
## Running
[Node.js](http://nodejs.org) (>=0.8.0) is required to run this app.
To install the dependencies locally, compile the CoffeScript, and run the demo server:
# from examples/derby
make run
To edit the code while running the demo server:
# from examples/derby
make
Open up another terminal window:
# from examples/derby
node server
Open the URL shown.
## Deploy on Heroku
To set up a git repository in this subdirectory and setup Heroku, run:
make deploy-setup
To deploy it to Heroku:
make heroku
var port = process.env.PORT || 3003;
require('derby').run(__dirname + '/lib/server', port);
http = require 'http'
path = require 'path'
express = require 'express'
gzippo = require 'gzippo'
derby = require 'derby'
todos = require '../todos'
serverError = require './serverError'
## SERVER CONFIGURATION ##
expressApp = express()
server = http.createServer expressApp
module.exports = server
store = derby.createStore
listen: server
require('./queries')(store)
ONE_YEAR = 1000 * 60 * 60 * 24 * 365
root = path.dirname path.dirname __dirname
publicPath = path.join root, 'public'
expressApp
.use(express.favicon())
# Gzip static files and serve from memory
.use(gzippo.staticGzip publicPath, maxAge: ONE_YEAR)
# Gzip dynamically rendered content
.use(express.compress())
# Adds req.getModel method
.use(store.modelMiddleware())
# Creates an express middleware from the app's routes
.use(todos.router())
.use(expressApp.router)
.use(serverError root)
## SERVER ONLY ROUTES ##
expressApp.all '*', (req) ->
throw "404: #{req.url}"
module.exports = (store) ->
store.query.expose 'todos', 'forGroup', (group) ->
@where('group').equals(group)
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
derby = require 'derby'
{get, view, ready} = derby.createApp module
derby.use(require '../../ui')
view.fn 'noItems',
get: (list) -> !list.length unless list is undefined
set: ->
view.fn 'oneItem',
get: (list) -> list.length == 1 unless list is undefined
# Redirect the visitor to a random todo list
get '/', (page) ->
page.redirect '/' + parseInt(Math.random() * 1e9).toString(36)
# Sets up the model, the reactive function for stats and renders the todo list
get '/:groupName', (page, model, {groupName}) ->
model.query('todos').forGroup(groupName).subscribe ->
model.set '_groupName', groupName
model.ref '_list.all', model.filter('todos')
.where('group').equals(groupName)
model.ref '_list.completed', model.filter('todos')
.where('group').equals(groupName)
.where('completed').equals(true)
model.ref '_list.active', model.filter('todos')
.where('group').equals(groupName)
.where('completed').notEquals(true)
model.set '_list.filterName', 'all'
# model.set '_filter', 'all'
# model.ref '_list.shown', '_list', '_filter'
# XXX 2012-12-04 Calling .get on keyed ref returns getter fn.
# We used to use the above keyed ref on _list, but when
# using derby master, it results in
# https://github.com/codeparty/derby/issues/179
model.ref '_list.shown', '_list.all'
page.render()
# Transitional route for enabling a filter
get from: '/:groupName', to: '/:groupName/:filterName',
forward: (model, {filterName}) ->
model.set '_list.filterName', filterName
model.ref '_list.shown', "_list.#{filterName}"
back: (model, params) ->
model.set '_list.filterName', filterName
model.ref '_list.shown', "_list.all"
get from: '/:groupName/:filterName', to: '/:groupName/:filterName',
forward: (model, {filterName}) ->
model.set '_list.filterName', filterName
model.ref '_list.shown', "_list.#{filterName}"
ready (model) ->
todos = model.at 'todos'
newTodo = model.at '_newTodo'
exports.add = ->
# Don't add a blank todo
text = newTodo.get().trim()
newTodo.set ''
return unless text
todos.add text: text, group: model.get('_groupName')
exports.del = (e, el) ->
# Derby extends model.at to support creation from DOM nodes
todos.del model.at(el).get('id')
exports.clearCompleted = ->
for {id} in model.get('_list.completed')
todos.del id
exports.clickToggleAll = ->
value = !!model.get('_list.active.length')
for {id} in model.get('_list.all')
todos.set id + '.completed', value
exports.submitEdit = (e, el) ->
el.firstChild.blur()
exports.startEdit = (e, el) ->
item = model.at(el)
item.set '_editing', true
input = el.parentElement.parentElement.lastChild.firstChild
input.value = item.get('text')
input.focus()
exports.endEdit = (e, el) ->
item = model.at(el)
item.set '_editing', false
if item.get('text').trim() == ''
todos.del item.get('id')
.connection {
position: absolute;
text-align: center;
top: 0;
left: 0;
width: 100%;
height: 0;
z-index: 99;
}
.connection > .alert {
background: #fff1a8;
border: 1px solid #999;
border-top: 0;
border-radius: 0 0 3px 3px;
display: inline-block;
line-height: 21px;
padding: 0 12px;
}
<connectionAlert:>
<div class="connection">
<!--
connected and canConnect are built-in properties of model. If a variable
is not defined in the current context, it will be looked up in the model
data and the model properties
-->
{#unless connected}
<p class="alert">
{#if canConnect}
<!-- Leading space is removed, and trailing space is maintained -->
Offline
<!-- a :self path alias is automatically created per component -->
{#unless :self.hideReconnect}
&ndash; <a x-bind="click:connect">Reconnect</a>
{/}
{else}
Unable to reconnect &ndash; <a x-bind="click:reload">Reload</a>
{/}
</p>
{/}
</div>
exports.connect = function() {
var model = this.model;
// Hide the reconnect link for a second after clicking it
model.set('hideReconnect', true);
setTimeout(function() {
model.set('hideReconnect', false);
}, 1000);
model.socket.socket.connect();
};
exports.reload = function() {
window.location.reload();
};
function ui(derby, options) {
derby.createLibrary({
filename: __filename,
styles: '../styles/ui',
scripts: {
connectionAlert: require('./connectionAlert')
}
}, options);
}
module.exports = ui;
ui.decorate = 'derby';
<!--
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>.
<Head:>
<link href="/components/todomvc-common/base.css" rel="stylesheet">
<Title:>
DerbyJS • TodoMVC
<Header:>
<ui:connectionAlert>
<Body:>
<section id="todoapp" data-framework="derby">
<app:todoHeader>
<section id="main" class="{#unless _list.shown}hidden{/}">
<input id="toggle-all" type="checkbox" checked="{noItems(_list.active)}" x-bind=click:clickToggleAll>
<label for="toggle-all">Mark all as complete</label>
<ul id="todo-list">{#each _list.shown}<app:todo>{/}</ul>
</section>
<app:todoFooter>
</section>
<app:info>
<todoHeader:>
<header id="header">
<h1>todos</h1>
<form x-bind=submit:add><input id="new-todo" placeholder="What needs to be done?" value={_newTodo} autofocus></form>
</header>
<todo:>
<li data-id={{id}} class="{#if .completed}completed{else}active{/}{#if ._editing} editing{/}">
<div class="view">
<input class="toggle" type="checkbox" checked="{.completed}">
<label x-bind=dblclick:startEdit>{.text}</label>
<button class="destroy" x-bind=click:del></button>
</div>
<form x-bind=submit:submitEdit>
<input class="edit" x-bind=blur:endEdit value="{.text}">
</form>
</li>
<todoFooter:>
<footer id="footer" class="{#unless _list.all}hidden{/}">
<span id="todo-count"><strong>{_list.active.length}</strong> item{#unless oneItem(_list.active)}s{/} left</span>
<ul id="filters">
<li>
<a href="/{{_groupName}}" class="{#if equal(_list.filterName, 'all')}selected{/}">All</a>
</li>
<li>
<a href="/{{_groupName}}/active" class="{#if equal(_list.filterName, 'active')}selected{/}">Active</a>
</li>
<li>
<a href="/{{_groupName}}/completed" class="{#if equal(_list.filterName, 'completed')}selected{/}">Completed</a>
</li>
</ul>
<button x-bind=click:clearCompleted id="clear-completed" class="{#unless _list.completed}non-completed{/}">
Clear completed
</button>
</footer>
<info:>
<footer id="info">
<h3>Open this <a href="/{{_groupName}}">app</a> in another browser, or share it with a friend to collaborate!</h3>
<p>Click on a todo to edit</p>
<p>Created by <a href="http://micknelson.wordpress.com">Michael Nelson</a> and <a href="https://github.com/lackac">László Bácsi</a></p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer>
......@@ -658,59 +658,6 @@
}]
}]
},
"derby": {
"name": "Derby",
"description": "MVC framework making it easy to write realtime, collaborative applications that run in both Node.js and browsers.",
"homepage": "derbyjs.com",
"examples": [{
"name": "Real-time Example",
"url": "http://todomvc.derbyjs.com",
"source_url": "examples/derby"
}],
"link_groups": [{
"heading": "Official Resources",
"links": [{
"name": "Introduction",
"url": "http://derbyjs.com/#introduction"
}, {
"name": "Getting Started",
"url": "http://derbyjs.com/#getting_started"
}, {
"name": "Applications built with Derby",
"url": "https://github.com/codeparty/derby/wiki/Community-Projects#website-showcase"
}, {
"name": "Blog",
"url": "http://blog.derbyjs.com"
}, {
"name": "FAQ",
"url": "https://github.com/codeparty/derby/wiki/Frequently-Asked-Questions"
}, {
"name": "Derby on GitHub",
"url": "https://github.com/codeparty/derby"
}]
}, {
"heading": "Articles and Guides",
"links": [{
"name": "Learning DerbyJS",
"url": "http://nickofnicks.com/2013/04/24/nodejs/derbyjs/learning-derbyjs/"
}, {
"name": "Screencast - 6 Things I'm Loving about DerbyJS",
"url": "http://micknelson.wordpress.com/2012/07/27/6-things-im-loving-about-derbyjs"
}]
}, {
"heading": "Community",
"links": [{
"name": "Derby on Stack Overflow",
"url": "http://stackoverflow.com/questions/tagged/derbyjs"
}, {
"name": "Mailing list on Google Groups",
"url": "https://groups.google.com/forum/?fromgroups#!forum/derbyjs"
}, {
"name": "Derby on Twitter",
"url": "http://twitter.com/derbyjs"
}]
}]
},
"dijon": {
"name": "Dijon",
"description": "An IOC/DI framework in Javascript, inspired by Robotlegs and Swiftsuspenders.",
......
......@@ -13,7 +13,7 @@ var excludedFrameworks = [
// selenium webdriver cannot see the shadow dom
'polymer',
// these implementations cannot be run offline, because they are hosted
'derby', 'firebase-angular', 'meteor', 'socketstream',
'firebase-angular', 'meteor', 'socketstream',
// YUI is a special case here, it is not hosted, but fetches JS files dynamically
'yui',
// these frameworks take a long time to start-up, and there is no easy way to determine when they are ready
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment