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

View File

@@ -0,0 +1,54 @@
http = require 'http'
path = require 'path'
express = require 'express'
gzippo = require 'gzippo'
derby = require 'derby'
todos = require '../todos'
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(todos.session())
# The router method creates an express middleware from the app's routes
.use(todos.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 ##
derby.use(require 'racer-db-mongo')
todos.createStore
listen: server
db: {type: 'Mongo', uri: 'mongodb://localhost/derby-todos'}

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

View File

@@ -0,0 +1,140 @@
{get, view, ready} = require('derby').createApp module
## ROUTES ##
get '/', (page) ->
page.redirect '/derby'
get '/:groupName', (page, model, {groupName}) ->
groupTodosQuery = model.query('todos').where('group').equals(groupName)
model.subscribe "groups.#{groupName}", groupTodosQuery, (err, group) ->
model.ref '_group', group
todoIds = group.at 'todoIds'
group.setNull 'id', groupName
# The refList supports array methods, but it stores the todo values
# on an object by id. The todos are stored on the object 'todos',
# and their order is stored in an array of ids at '_group.todoIds'
model.refList '_todoList', 'todos', todoIds
# Add some default todos if this is a new group. Items inserted into
# a refList will automatically get an 'id' property if not specified
unless todoIds.get()
model.push '_todoList',
{group: groupName, text: 'Example todo'},
{group: groupName, text: 'Another example'},
{group: groupName, text: 'This one is done already', completed: true}
# Create a reactive function that automatically keeps '_remaining'
# updated with the number of remaining todos
model.fn '_remaining', '_todoList', (list) ->
remaining = 0
for todo in list
remaining++ unless todo?.completed
return remaining
page.render()
# TODO Implement this commented out API
#get '/:groupName', (page, model, {groupName, query}) ->
# model.subscribe "groups.#{groupName}", (group) ->
# model.ref '_group', group
## group.setNull 'id', groupName
# todoIds = group.at 'todoIds'
# model.subscribe query('todos').where('id').within(todoIds), ->
# # The refList supports array methods, but it stores the todo values
# # on an object by id. The todos are stored on the object 'todos',
# # and their order is stored in an array of ids at '_group.todoIds'
# todoList = model.refList '_todoList', 'todos', todoIds
# unless todoIds.get()
# todoList.push
# {text: 'Example todo', tags: ['wknd']},
# {text: 'Another example', tags: ['wknd', 'work']},
# {text: 'This one is done already', tags: ['work'], completed: true}
#
# # Create a reactive function that automatically keeps '_remaining'
# # updated with the number of remaining todos
# model.fn '_remaining', '_todoList', (list) ->
# remaining = 0
# for todo in list
# remaining++ unless todo.completed
# return remaining
#
# if tags = query.tags?.split ','
# # TODO Hide / show tag classes
# else
# # TODO Hide / show tag classes
#
# page.render()
## CONTROLLER FUNCTIONS ##
ready (model) ->
list = model.at '_todoList'
# Make the list draggable using jQuery UI
ul = $('#todos')
ul.sortable
handle: '.handle'
axis: 'y'
containment: '#dragbox'
update: (e, ui) ->
item = ui.item[0]
domId = item.id
id = item.getAttribute 'data-id'
to = ul.children().index(item)
# Use the Derby ignore option to suppress the normal move event
# binding, since jQuery UI will move the element in the DOM.
# Also, note that refList index arguments can either be an index
# or the item's id property
list.pass(ignore: domId).move {id}, to
list.on 'set', '*.completed', (i, completed, previous, isLocal) ->
# Move the item to the bottom if it was checked off
list.move i, -1 if completed && isLocal
newTodo = model.at '_newTodo'
exports.add = ->
# Don't add a blank todo
return unless text = view.escapeHtml newTodo.get()
newTodo.set ''
# Insert the new todo before the first completed item in the list
# or append to the end if none are completed
for todo, i in list.get()
break if todo.completed
list.insert i, {text, group: model.get '_group.id'}
exports.del = (e) ->
# Derby extends model.at to support creation from DOM nodes
model.at(e.target).remove()
showReconnect = model.at '_showReconnect'
showReconnect.set true
exports.connect = ->
showReconnect.set false
setTimeout (-> showReconnect.set true), 1000
model.socket.socket.connect()
exports.reload = -> window.location.reload()
exports.shortcuts = (e) ->
return unless e.metaKey || e.ctrlKey
code = e.which
return unless command = (switch code
when 66 then 'bold' # Bold: Ctrl/Cmd + B
when 73 then 'italic' # Italic: Ctrl/Cmd + I
when 32 then 'removeFormat' # Clear formatting: Ctrl/Cmd + Space
when 220 then 'removeFormat' # Clear formatting: Ctrl/Cmd + \
else null
)
document.execCommand command, false, null
e.preventDefault() if e.preventDefault
return false
# Tell Firefox to use elements for styles instead of CSS
# See: https://developer.mozilla.org/en/Rich-Text_Editing_in_Mozilla
document.execCommand 'useCSS', false, true
document.execCommand 'styleWithCSS', false, false