mirror of
https://github.com/sstent/node.git
synced 2026-01-27 23:51:45 +00:00
updated app
This commit is contained in:
94
node_modules/derby-examples/sink/src/app/bindings-bench.coffee
generated
vendored
Normal file
94
node_modules/derby-examples/sink/src/app/bindings-bench.coffee
generated
vendored
Normal 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
49
node_modules/derby-examples/sink/src/app/home.coffee
generated
vendored
Normal 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
29
node_modules/derby-examples/sink/src/app/index.coffee
generated
vendored
Normal 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()
|
||||
52
node_modules/derby-examples/sink/src/app/leaderboard.coffee
generated
vendored
Normal file
52
node_modules/derby-examples/sink/src/app/leaderboard.coffee
generated
vendored
Normal 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
|
||||
40
node_modules/derby-examples/sink/src/app/live-css.coffee
generated
vendored
Normal file
40
node_modules/derby-examples/sink/src/app/live-css.coffee
generated
vendored
Normal 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
22
node_modules/derby-examples/sink/src/app/shared.coffee
generated
vendored
Normal 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
|
||||
125
node_modules/derby-examples/sink/src/app/sortableTable.coffee
generated
vendored
Normal file
125
node_modules/derby-examples/sink/src/app/sortableTable.coffee
generated
vendored
Normal 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
70
node_modules/derby-examples/sink/src/app/table.coffee
generated
vendored
Normal 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
|
||||
Reference in New Issue
Block a user