cleaner tree

This commit is contained in:
Galen Wolfe-Pauly 2016-01-20 15:23:13 -08:00
parent 80b1245789
commit dcdba18903
27 changed files with 0 additions and 1944 deletions

View File

@ -1,69 +0,0 @@
/* */
/*-- bau --*/
/* */
@font-face
font-family "bau"
src url("//storage.googleapis.com/urbit-extra/bau.woff")
font-weight 400
font-style normal
@font-face
font-family "bau"
src url("//storage.googleapis.com/urbit-extra/bau-italic.woff")
font-weight 400
font-style italic
@font-face
font-family "bau"
src url("//storage.googleapis.com/urbit-extra/bau-medium.woff")
font-weight 500
font-style normal
@font-face
font-family "bau"
src url("//storage.googleapis.com/urbit-extra/bau-mediumitalic.woff")
font-weight 500
font-style italic
@font-face
font-family "bau"
src url("//storage.googleapis.com/urbit-extra/bau-bold.woff")
font-weight 600
font-style normal
@font-face
font-family "bau"
src url("//storage.googleapis.com/urbit-extra/bau-bolditalic.woff")
font-weight 600
font-style italic
@font-face
font-family "bau"
src url("//storage.googleapis.com/urbit-extra/bau-super.woff")
font-weight 600
font-style normal
@font-face
font-family "bau"
src url("//storage.googleapis.com/urbit-extra/bau-superitalic.woff")
font-weight 600
font-style italic
/* */
/*-- scp --*/
/* */
@font-face
font-family "scp"
src url("//storage.googleapis.com/urbit-extra/scp-extralight.woff")
font-weight 200
font-style normal
@font-face
font-family "scp"
src url("//storage.googleapis.com/urbit-extra/scp-light.woff")
font-weight 300
font-style normal
@font-face
font-family "scp"
src url("//storage.googleapis.com/urbit-extra/scp-regular.woff")
font-weight 400
font-style normal
@font-face
font-family "scp"
src url("//storage.googleapis.com/urbit-extra/scp-medium.woff")
font-weight 500
font-style normal

View File

@ -1,175 +0,0 @@
.bar
margin-top 2rem
margin-bottom 2rem
& > div
display inline-block
a.logo
display inline-block
height 2rem
vertical-align middle
border none
img.logo
margin-right 18px
margin-top 0
ul
margin 0
line-height 2rem
display inline-block
li::before
content ''
padding-right none
li
display inline-block
margin-bottom 0
margin-right 1rem
vertical-align middle
li a
border-bottom none
text-decoration underline
li a h1
margin 0
line-height inherit
text-transform capitalize
font-size 1.2rem
h1
text-transform capitalize
font-size 1rem
font-weight 400
letter-spacing .03rem
.lead
#body
margin-top 3rem
margin-top 0
h1
margin-top 1rem
vertical-align middle
line-height 4rem
&.fold
margin-top 6rem
.list li h1
line-height 2rem
&
font-size 1.6rem
line-height 2.6rem
a
line-height 1rem
p
font-size 1.6rem
line-height 3rem
.mono
font-size 1.3rem
.footer
margin 4rem 0 4rem 0
p
margin 0
font-size .7rem
code
line-height 1rem
font-size .7rem
input.email
border-radius 0
font inherit
font-family 'scp'
font-weight 300
line-height 2rem
min-width 2rem
border 0
outline 0
background-color transparent
border-bottom 3px dotted #000
margin-right 1rem
display inline-block
&.valid
color #99F27C
&.error
color #F74040
.email:empty:not(:focus):before
content attr(data-ph)
::-webkit-input-placeholder
color #e6e7e8
:-moz-placeholder
color #e6e7e8
::-moz-placeholder
color #e6e7e8
:-ms-input-placeholder
color #e6e7e8
button.submit
font inherit
border 0
background-color #fff
border-bottom 3px solid #000
font-size 1.6rem
line-height 1.6rem
display inline-block
text-align left
margin-top 1rem
height 2rem
padding 0 .6rem
.date
font-weight 400
@media only screen and (max-width: 1170px)
#cont.lead
top 0rem
@media only screen and (min-width: 320px) and (max-width: 1024px)
#cont.lead
top 0rem
font-size 1rem
line-height 1.6rem
.post h1
font-size 2rem
line-height 3rem
.bar
margin-top 1rem
margin-bottom 1rem
.list li h1,
font-size 1rem
line-height 1.6rem
img.logo
display block
margin-bottom 1rem
h1.leader,
h1.fold
font-size 1.6rem
line-height 3rem
margin-left 0
.list li,
.list li a,
.list li h1,
font-size 1rem
line-height 1.6rem
input.email
font-size 1.2rem
width 100%
button.submit
font-size 1rem
.date,
div.footer
font-size .6rem

View File

@ -1,447 +0,0 @@
@import 'fonts'
body
html
font-family "bau","Helvetica Neue",helvetica,arial,sans-serif
code
pre
li:before
.spin
#bred a
.mono
h3.time
font-family "scp","Courier New",courier,monospace
body
html
font-size 18px
font-weight 400
line-height 1.6rem
-webkit-text-size-adjust none
p
font-size 1.2rem
line-height 2rem
a
color #000
border-bottom 1px solid #000
text-decoration none
display inline-block
line-height .8rem
a:visited
opacity .5
a code
line-height inherit
hr
display inline-block
width 6rem
border 0
border-top 2px solid #f4f4f4
h1
margin-top 4rem
line-height 2.6rem
#body > div > h1:first-of-type
#body div.short > h1:first-of-type
margin-top 1rem
h2
h3
margin 0
margin-top 2rem
h1
h2
h3
h4
strong
font-weight 500
h4
margin-bottom .3rem
h5
font-style italic
font-weight 200
margin 0
h1 code
h2 code
h3 code
font-size inherit
padding .3rem
pre
code
font-size 1rem
pre
background-color #f5f5f5
padding .3rem
margin-left -.3rem
overflow-y scroll
code
line-height 1.2rem
background-color #f4f4f4
margin-top -.05rem
padding .2rem
display inline-block
white-space pre
blockquote
background-color #f5f5f5
margin 0
padding 1rem
font-style italic
margin-left 3rem
blockquote p
margin 0
blockquote em
font-style normal
ul
list-style none
padding 0
li:before
font-family 'scp'
content "\2022"
padding-right .3rem
font-size 1rem
font-weight 500
#nav
#cont
left 50%
#cont
width 42rem
margin-left -21rem
background-color #fff
z-index 1
#nav
position fixed
top 0rem
width 57rem
padding-top 1rem
z-index 0
margin-left -32rem
overflow hidden
transition opacity 1s ease-in-out
#nav.moving
opacity 1
transition opacity .3s ease-in-out
#nav:hover
opacity 1
transition opacity .3s ease-in-out
#cont
position relative
top 0
margin-bottom 9rem
.loading
display inline-block
.spin
color #fff
padding .6rem
font-size .7rem
font-weight 600
letter-spacing .1rem
z-index 3
.loading > .spin
background-color #555
#body .loading > .spin
background-color #000
.spin.state-0:before
content "\2599"
.spin.state-1:before
content "\259B"
.spin.state-2:before
content "\259C"
.spin.state-3:before
content "\259F"
#load.load
display inline-block
font-weight 500
position fixed
top 0
left 0
width 100%
height 100%
background-color rgba(10,10,10,.4)
opacity 1
transition opacity 1s ease-in-out
z-index 4
img.logo
height 2rem
width 2rem
h3.time
margin-top: .3rem
font-size .7rem
font-weight 200
#nav .links > div
display inline-block
vertical-align top
#nav #sibs
width 8rem
transition margin-top .3s ease-in-out
overflow hidden
#nav #sibs > div
margin-bottom .6rem
.focus #sibs
margin-top 0 !important
transition margin-top .3s ease-in-out
#nav a
.list > li > a
display inline
#nav a
text-transform uppercase
font-size .7rem
line-height 1rem
font-weight 200
letter-spacing 1px
.link-next
margin-top 2rem
font-weight 500
.list > li
margin-bottom 1rem
.list > li > a h1
font-size inherit
line-height inherit
#nav .active a
font-weight 500
text-decoration none
#up
padding-right 1rem
margin-top -8px
#sides
float right
#sides a
display inline-block
margin-right .6rem
.arow-up
.arow-next
.arow-prev
width 0
height 0
border .4rem solid transparent
.arow-up
border-bottom .6rem solid #000
.arow-next
border-left .6rem solid #000
.arow-prev
border-right .6rem solid #000
#bred
width 5rem
padding-right 1rem
text-align right
font-size .6rem
white-space nowrap
overflow hidden
#bred a
text-transform lowercase
vertical-align top
#bred > div
float right
#bred > div > div
display inline-block
margin-top -.2rem
#bred a
#kids a
margin-right .3rem
#bred a
margin-left .3rem
.short
width 32rem
.list h1
.list li a > div p
margin 0
.list li a > div
.list li a > div p
display inline
.list li a > div p
margin-left .3rem
.list li a > div p:first-child
margin-left 0
.list li a > div p code
font-size .7rem
font-weight 400
text-transform none
.list li a h1 code
text-transform lowercase
.list li a code
padding .2rem
.list h1
.list li a > div div
display inline
.list li a > div div
margin-left .6rem
overflow hidden
.list h1
font-size .7rem
div.root
h1
margin-bottom 2rem
.list .sub
margin-left 0
margin-right .6rem
div.root > p
width 27rem
margin-top 2rem
h2.sub
font-size .7rem
font-weight 400
line-height 1rem
letter-spacing 1px
margin-top 0
text-transform uppercase
div.toc
margin-top 3rem
margin-bottom 3rem
h1
h2
h3
h4
font-weight 400
cursor pointer
text-decoration underline
font-size 1.2rem
margin-top .3rem
margin-bottom .3rem
h2
margin-left 1rem
h3
margin-left 2rem
h4
margin-left 3rem
h1.t
font-weight 500
font-size 2rem
text-decoration none
margin-bottom 2rem
#body .spam
width 9rem
background-color #555
padding 1rem
letter-spacing 1px
font-weight 500
margin-bottom 2rem
#body .spam
#body .spam a
color #fff
#body .spam a
border-color #fff
#body .CodeMirror
font-size .8rem
line-height 1rem
#body .CodeMirror .cm-header
font-weight 200
#body .CodeMirror-gutters
background-color #fff
padding-right 1rem
margin-left -1rem
.footer p
font-family 'scp'
font-size .7rem
font-weight 400
margin-top 3rem
color #ccc
.error
color rgba(249,23,51,1)
.warning
background-color rgb(255,53,55)
padding 1rem
width 18rem
margin 2rem 0
color #fff
a
color inherit
border-color #fff
h1
font-size 1rem
h1
p
margin 0 .3rem
.warning.w
width auto
@import 'posts'
@import 'leads'
@import 'video'
@import 'mobile'

View File

@ -1,138 +0,0 @@
/* laptops / small screens ----------- */
@media only screen and (max-width: 1170px)
#nav
#nav > div
#nav.up
#nav.top
#nav .focus
transform: translate3d(0,0,0);
-webkit-transform: translate3d(0,0,0);
#nav
position fixed
top 0
opacity 1
width 42rem
margin-left -21rem
background-color #fff
z-index 2
#nav a
white-space nowrap
#nav #sibs
width 12rem
#nav #sibs > div
height 20px
margin-bottom 4px
#nav #sibs > div.active a
#nav #sibs > div a
border-bottom none
text-decoration underline
#nav.m-down
#nav.m-up
position absolute
#nav.m-down.m-fixed
position fixed
top 0
#nav > div > div
max-height 2rem
overflow hidden
transition max-height .3s ease-in-out
#nav .focus
max-height 40rem
transition max-height .3s ease-in-out
#cont
top 3rem
#cont.no-anchor
top 0
/* tablets + phones ----------- */
@media only screen and (min-width: 320px) and (max-width: 1024px)
body
html
font-size 21px
p
font-size 1rem
line-height 2rem
#nav
#cont
width 94%
padding-left 3%
margin-left 0
#nav
position fixed
padding-top 0
opacity 1
left 0
z-index 2
#nav > div > div
max-height 1.2rem
#nav > div
padding-top .6rem
#nav #sibs
width 11rem
padding-top 0
#nav #sibs > div
height 20px
line-height 20px
#nav a
display inline-block
font-size .7rem
#nav #sides
float none
margin-left 1rem
#nav .arow-up
#nav .arow-next
#nav .arow-prev
margin-right 0
border .4rem solid transparent
#nav .arow-up
border-bottom .6rem solid #000
#nav .arow-next
border-left .6rem solid #000
#nav .arow-prev
margin-right 1rem
border-right .6rem solid #000
#cont
left 0
padding-bottom 9rem
#cont h1:first-child
margin-top 0
.short
width 100%
/* phones portrait and landscape ----------- */
@media only screen and (min-device-width: 320px) and (max-device-width: 480px)
#nav > div > div
max-height 1.6rem
#nav a
line-height auto
font-size .7rem
#nav #sibs > div
height 20px
line-height 20px

View File

@ -1,50 +0,0 @@
div.post
h1
font-size 2.8rem
line-height 4rem
margin-top 1rem
margin-bottom 1rem
h2
font-family 'scp'
font-size .7rem
line-height 1rem
letter-spacing 1px
h3
margin-top 0
font-size .7rem
font-weight 200
letter-spacing .1rem
text-transform uppercase
h3::before
content '\2014'
margin-right .3rem
.list li
margin-bottom 0
font-size 1.2rem
p
font-size 1.2rem
line-height 2.2rem
li p
display inline
p.ib
margin-top 0
@media only screen and (min-width: 320px) and (max-width: 1024px)
div.post
h2
h3
font-size .5rem
p
font-size 1rem
line-height 2rem
li h1
font-weight 400
li::before
font-weight 200

View File

@ -1,15 +0,0 @@
.video
iframe
width 42rem
height 24rem
.leader
font-size 2rem
font-weight 500
line-height 2.6rem
margin-bottom 4rem
.short img
margin-top 2rem
width 42rem

View File

@ -1,16 +0,0 @@
TreeDispatcher = require '../dispatcher/Dispatcher.coffee'
TreePersistence = require '../persistence/TreePersistence.coffee'
module.exports =
loadPath: (path,data) ->
TreeDispatcher.handleServerAction {path,data,type:"path-load"}
sendQuery: (path,query) ->
return unless query?
if path.slice(-1) is "/" then path = path.slice(0,-1)
TreePersistence.get path,query,(err,res) => @loadPath path,res
setCurr: (path) ->
TreeDispatcher.handleViewAction
type:"set-curr"
path:path

View File

@ -1,163 +0,0 @@
clas = require 'classnames'
BodyComponent = React.createFactory require './BodyComponent.coffee'
query = require './Async.coffee'
reactify = require './Reactify.coffee'
TreeStore = require '../stores/TreeStore.coffee'
TreeActions = require '../actions/TreeActions.coffee'
recl = React.createClass
{div,a} = React.DOM
Links = React.createFactory query {
path:'t'
kids:
name:'t'
head:'r'
meta:'j'
}, (recl
displayName: "Links"
render: -> div {className:'links'},
@props.children,
@renderUp(),
@renderSibs(),
@renderArrows()
renderUp: ->
if @props.sein
div {id:"up",key:"up"}, @renderArrow "up", @props.sein
renderSibs: ->
keys = window.tree.util.getKeys @props.kids
if keys.indexOf(@props.curr) isnt -1
style = {marginTop: -24 * (keys.indexOf @props.curr) + "px"}
div {id:"sibs",style}, keys.map (key) =>
href = window.tree.basepath @props.path+"/"+key
data = @props.kids[key]
head = data.meta.title if data.meta
head ?= @toText data.head
head ||= key
className = clas active: key is @props.curr
(div {className,key}, (a {href,onClick:@props.onClick}, head))
renderArrow: (name, path) ->
href = window.tree.basepath path
(a {href,key:"arow-#{name}",className:"arow-#{name}"},"")
renderArrows: ->
keys = window.tree.util.getKeys @props.kids
if keys.length > 1
index = keys.indexOf(@props.curr)
prev = index-1
next = index+1
if prev < 0 then prev = keys.length-1
if next is keys.length then next = 0
prev = keys[prev]
next = keys[next]
if @props.sein
sein = @props.sein
if sein is "/" then sein = ""
if prev or next then _.filter [
div {id:"sides",key:"sides"},
if prev then @renderArrow "prev", "#{sein}/#{prev}"
if next then @renderArrow "next", "#{sein}/#{next}"
]
toText: (elem)-> reactify.walk elem,
()->''
(s)->s
({c})->(c ? []).join ''
), recl
displayName: "Links_loading"
render: -> div {className:'links'}, @props.children, @_render()
_render: -> div {id:"sibs"}, div {className:"active"}, a {}, @props.curr
CLICK = 'a'
module.exports = query {
sein:'t'
path:'t'
name:'t'
meta:'j'
},(recl
displayName: "Anchor"
getInitialState: -> url: window.location.pathname
onClick: -> @toggleFocus()
onMouseOver: -> @toggleFocus true
onMouseOut: -> @toggleFocus false
onTouchStart: -> @ts = Number Date.now()
onTouchEnd: -> dt = @ts - Number Date.now()
toggleFocus: (state) -> $(@getDOMNode()).toggleClass 'focus',state
componentWillUnmount: -> clearInterval @interval; $('body').off 'click', CLICK
componentDidUpdate: -> @setTitle()
componentDidMount: ->
@setTitle()
@interval = setInterval @checkURL,100
# $('body').on 'keyup', (e) =>
# switch e.keyCode
# when 37 then @goTo @props.prev # left
# when 39 then @goTo @props.next # right
_this = @
$('body').on 'click', CLICK, (e) ->
href = $(@).attr('href')
id = $(@).attr('id')
if href and not /^https?:\/\//i.test(href)
e.preventDefault()
e.stopPropagation()
if href?[0] isnt "/"
href = (document.location.pathname.replace /[^\/]*\/?$/, '') + href
_this.goTo window.tree.fragpath href
if id
window.location.hash = id
setTitle: ->
title = $('#cont h1').first().text() || @props.name
title = @props.meta.title if @props.meta?.title
document.title = "#{title} - #{@props.path}"
setPath: (href,hist) ->
href_parts = href.split("#")
next = href_parts[0]
if next.substr(-1) is "/" then next = next.slice(0,-1)
href_parts[0] = next
if hist isnt false
history.pushState {}, "", window.tree.basepath href_parts.join ""
if next isnt @props.path
React.unmountComponentAtNode $('#cont')[0]
TreeActions.setCurr next
React.render (BodyComponent {}, ""),$('#cont')[0]
reset: ->
$("html,body").animate {scrollTop:0}
# $("#cont").attr 'class',''
$('#nav').attr 'style',''
$('#nav').removeClass 'scrolling m-up'
$('#nav').addClass 'm-down m-fixed'
goTo: (path) ->
@toggleFocus false
@reset()
@setPath path
checkURL: ->
if @state.url isnt window.location.pathname
@reset()
@setPath (window.tree.fragpath window.location.pathname),false
@setState url: window.location.pathname
render: ->
if @props.meta.anchor is 'none'
return (div {}, "")
obj = {@onMouseOver,@onMouseOut,@onClick,@onTouchStart,@onTouchEnd}
if _.keys(window).indexOf("ontouchstart") isnt -1
delete obj.onMouseOver
delete obj.onMouseOut
div obj, Links {
@onClick
curr:@props.name
dataPath:@props.sein
sein:@props.sein
}), "div"

View File

@ -1,67 +0,0 @@
_load = require './LoadComponent.coffee'
TreeStore = require '../stores/TreeStore.coffee'
TreeActions = require '../actions/TreeActions.coffee'
recl = React.createClass
{div,span,code} = React.DOM
module.exports = (queries, Child, load=_load)-> recl
displayName: "Async"
getInitialState: -> @stateFromStore()
_onChangeStore: ->
if @isMounted() then @setState @stateFromStore()
getPath: ->
path = @props.dataPath ? TreeStore.getCurr()
if path.slice(-1) is "/"
path.slice 0,-1
else path
stateFromStore: -> got: TreeStore.fulfill @getPath(), queries
componentDidMount: ->
TreeStore.addChangeListener @_onChangeStore
@checkPath()
componentWillUnmount: ->
TreeStore.removeChangeListener @_onChangeStore
componentDidUpdate: (_props,_state) ->
if _props isnt @props
@setState @stateFromStore()
@checkPath()
checkPath: -> TreeActions.sendQuery @getPath(), @filterQueries()
filterQueries: -> @filterWith @state.got, queries
filterWith: (have,_queries)->
return _queries unless have?
request = {}
for k of _queries when k isnt 'kids'
request[k] = _queries[k] unless have[k] isnt undefined
if _queries.kids?
if not have.kids?
request.kids = _queries.kids
else
request.kids = {}
for k,kid of have.kids
_.merge request.kids, @filterWith kid, _queries.kids
if _.isEmpty request.kids
delete request.kids
request unless _.isEmpty request
scrollHash: -> @getHashElement()?.scrollIntoView()
getHashElement: ->
{hash} = document.location
if hash then document.getElementById hash[1..]
render: -> div {},
if @filterQueries()?
React.createElement load, @props
else
if not @getHashElement() # onmount?
setTimeout @scrollHash,0
React.createElement Child,
(_.extend {}, @props, @state.got),
@props.children

View File

@ -1,84 +0,0 @@
clas = require 'classnames'
query = require './Async.coffee'
reactify = require './Reactify.coffee'
recl = React.createClass
rele = React.createElement
{div,p,img,a} = React.DOM
extras =
spam: recl
displayName:"Spam"
render: ->
if document.location.hostname isnt 'urbit.org'
return (div {})
(div {className:'spam'},
(a {href:"http://urbit.org#sign-up"}, "Sign up")
" for our newsletter."
)
logo: recl
displayName:"Logo"
render: ->
{color} = @props
if color is "white" or color is "black" # else?
src = "//storage.googleapis.com/urbit-extra/logo/logo-#{color}-100x100.png"
(a {href:"http://urbit.org",style:{border:"none"}},
(img {src,className:"logo"})
)
next: query {
path:'t'
kids:
name:'t'
head:'r'
meta:'j'
}, recl
displayName: "Next"
render: ->
curr = @props.kids[@props.curr]
if curr?.meta?.next
keys = window.tree.util.getKeys @props.kids
if keys.length > 1
index = keys.indexOf(@props.curr)
next = index+1
if next is keys.length then next = 0
next = keys[next]
next = @props.kids[next]
if next
return (div {className:"link-next"}, [
(a {href:"#{@props.path}/#{next.name}"}, "Next: #{next.meta.title}")
])
return (div {},"")
footer: recl
displayName: "Footer"
render: ->
(div {className:"footer"}, (p {}, "This page was served by Urbit."))
module.exports = query {
body:'r'
name:'t'
path:'t'
meta:'j'
sein:'t'
}, recl
displayName: "Body"
render: ->
className = clas (@props.meta.layout?.split ',')
extra = (name,props={})=>
if @props.meta[name]? then React.createElement extras[name], props
(div {
id:'body',
key:"body"+@props.path
className
},
extra 'spam'
extra 'logo', color: @props.meta.logo
reactify @props.body
extra 'next', {dataPath:@props.sein,curr:@props.name}
extra 'footer'
)

View File

@ -1,9 +0,0 @@
recl = React.createClass
{div,textarea} = React.DOM
module.exports = recl
render: -> div {}, textarea ref:'ed', value:@props.value
componentDidMount: ->
CodeMirror.fromTextArea @refs.ed.getDOMNode(),
readOnly:true
lineNumbers:true

View File

@ -1,11 +0,0 @@
recl = React.createClass
{div} = React.DOM
module.exports =
codemirror: require './CodeMirror.coffee'
search: require './SearchComponent.coffee'
list: require './ListComponent.coffee'
kids: require './KidsComponent.coffee'
toc: require './TocComponent.coffee'
email: require './EmailComponent.coffee'
lost: recl render: -> (div {}, "<lost(", @props.children, ")>")

View File

@ -1,45 +0,0 @@
reactify = require './Reactify.coffee'
recl = React.createClass
{div,p,button,input} = React.DOM
module.exports = recl
displayName: "email"
getInitialState: -> {submit:false,email:""}
onClick: -> @submit()
onKeyUp: (e) ->
email = @$email.val()
valid = (email.indexOf('@') != -1 &&
email.indexOf('.') != -1 &&
email.length > 7 &&
email.split(".")[1].length > 1 &&
email.split("@")[0].length > 0 &&
email.split("@")[1].length > 4)
@$email.toggleClass 'valid',valid
@$email.removeClass 'error'
if e.keyCode is 13
if valid is true
@submit()
e.stopPropagation()
e.preventDefault()
return false
else
@$email.addClass 'error'
submit: ->
$.post @props.dataPath,{email:@$email.val()},() =>
@setState {submit:true}
componentDidMount: -> @$email = $('input.email')
render: ->
if @state.submit is false
cont = [
(input {key:"field",className:"email",placeholder:"your@email.com",@onKeyUp}, @state.email)
(button {key:"submit",className:"submit",@onClick}, "Sign up")
]
else
cont = [(div {className:"submitted"},"Got it. Thanks!")]
(p {className:"email",id:"sign-up"}, cont)

View File

@ -1,42 +0,0 @@
reactify = require './Reactify.coffee'
query = require './Async.coffee'
recl = React.createClass
{div,a,ul,li,hr} = React.DOM
module.exports = query {kids: {body:'r', meta:'j'}}, recl
displayName: "Kids"
render: ->
klass = "kids"
if @props.dataType then klass += " #{@props.dataType}"
sorted = true
keyed = {}
for k,v of @props.kids
if @props.sortBy
if @props.sortBy is 'date'
if not v.meta?.date?
sorted = false
continue
d = v.meta.date.slice(1).split "."
if d.length < 3
sorted = false
continue
str = "#{d[0]}-#{d[1]}-#{d[2]}"
if d.length > 3
str += " #{d[3]}:#{d[4]}:#{d[5]}"
_k = Number(new Date(str))
keyed[_k] = k
else
if not v.meta?.sort? then sorted = false
keyed[Number(v.meta?.sort)] = k
if sorted is false then keyed = _.keys this.props.kids
keys = _.keys(keyed).sort()
if @props.sortBy is 'date' then keys.reverse()
div {className:klass},
for k in keys
elem = @props.kids[keyed[k]] ? ""
[(div {key:keyed[k]}, reactify elem.body), (hr {},"")]

View File

@ -1,109 +0,0 @@
clas = require 'classnames'
reactify = require './Reactify.coffee'
query = require './Async.coffee'
recl = React.createClass
{div,pre,span,a,ul,li,h1} = React.DOM
module.exports = query {
path:'t'
kids:
snip:'r'
head:'r'
meta:'j'
}, recl
displayName: "List"
render: ->
k = clas
list: true
@props.dataType
posts: @props.dataType is 'post' # needs css update
default: @props['data-source'] is 'default'
kids = @renderList()
unless kids.length is 0 and @props.is404?
return (ul {className:k}, kids)
div {className:k},
h1 {className:'error'}, 'Error: Empty path'
div {},
pre {}, @props.path
span {}, 'is either empty or does not exist.'
renderList: ->
# check if kids all have a sort meta tag
sorted = true
_keys = []
for k,v of @props.kids
if @props.sortBy
if @props.sortBy is 'date'
if not v.meta?.date? then sorted = false
_k = Number v.meta.date.slice(1).replace /\./g,""
_keys[_k] = k
else
if not v.meta?.sort? then sorted = false
_keys[Number(v.meta?.sort)] = k
if @props.sortBy is 'date' then _keys.reverse()
if sorted isnt true
_keys = _.keys(@props.kids).sort()
if @props.dataType is 'post' then _keys=_keys.reverse()
for item in _.values _keys
path = @props.path+"/"+item
elem = @props.kids[item]
if elem.meta.hide? then continue
href = window.tree.basepath path
if elem.meta.link then href = elem.meta.link
parts = []
title = null
if elem.meta?.title
title =
gn: 'h1'
c: [elem.meta.title]
if not title && elem.head.c.length > 0
title = elem.head
if not title
title =
gn: 'h1'
c: [item]
unless @props.titlesOnly # redundant? this seems familiar
if @props.dataDates
_date = elem.meta.date
if not _date or _date.length is 0 then _date = ""
date =
gn: 'div'
ga:
className: 'date'
c: [_date]
parts.push date
parts.push title
unless @props.titlesOnly # redundant? this seems familiar
if @props.dataPreview
if @props.dataType is 'post' and not elem.meta.preview
parts.push (elem.snip.c.slice 0,2)...
else
if elem.meta.preview
preview =
gn: 'p'
c: [elem.meta.preview]
else
preview = elem.snip
parts.push preview
li {key:item,className:@props.dataType ? ""},
a {href,className:(clas preview: @props.dataPreview?)},
reactify
gn: 'div'
c: parts
# if not @props.dataPreview? then (h1 {},item)
# else if @props.dataType is 'post'
# head =
# if elem.meta?.title
# gn: 'h1'
# c: [elem.meta.title]
# else elem.head
# reactify
# gn: 'div'
# c: [head, (elem.snip.c.slice 0,2)...]
# else if @props.titlesOnly? then reactify elem.head
# else div {}, (reactify elem.head), (reactify elem.snip)

View File

@ -1,18 +0,0 @@
recl = React.createClass
{div,input,textarea} = React.DOM
module.exports = recl
displayName: "Load"
getInitialState: -> {anim: 0}
componentDidMount: -> @interval = setInterval @setAnim, 100
componentWillUnmount: -> clearInterval @interval
setAnim: ->
anim = @state.anim+1
if anim > 3 then anim = 0
@setState {anim:anim}
render: -> (div {className:"loading"},
(div {className:"spin state-#{@state.anim}"}, ""))

View File

@ -1,30 +0,0 @@
recl = React.createClass
rele = React.createElement
{div,span} = React.DOM
load = React.createFactory require './LoadComponent.coffee'
walk = (root,_nil,_str,_comp)->
# manx: {fork: ["string", {gn:"string" ga:{dict:"string"} c:{list:"manx"}}]}
_walk = (elem,key)-> switch
when !elem? then _nil()
when typeof elem == "string" then _str elem
when elem.gn?
{gn,ga,c} = elem
c = (c?.map _walk) ? []
_comp.call elem, {gn,ga,c}, key
else throw "Bad react-json #{JSON.stringify elem}"
_walk root
Virtual = recl
displayName: "Virtual"
render: ->
{components} = window.tree
walk @props.manx,
()-> (load {},"")
(str)-> str
({gn,ga,c},key)-> rele (components[gn] ? gn),
(_.extend {key}, ga),
c
reactify = (manx,key)-> rele Virtual, {manx,key}
module.exports = _.extend reactify, {walk,Virtual}

View File

@ -1,48 +0,0 @@
query = require './Async.coffee'
reactify = require './Reactify.coffee'
recl = React.createClass
{a,div,input} = React.DOM
module.exports = query {name:'t', kids: sect:'j'}, recl
hash:null
displayName: "Search"
getInitialState: -> search: 'wut'
onKeyUp: (e)-> @setState search: e.target.value
wrap: (elem,dir,path)->
path = path[...-1] if path[-1...] is "/"
href = @props.name+"/"+dir+path
if elem?.ga?.id
{gn,ga,c} = elem
ga = _.clone ga
href += "#"+ga.id
delete ga.id
elem = {gn,ga,c}
{gn:'div', c:[{gn:'a', ga:{href}, c:[elem]}]}
render: -> div {},
input {@onKeyUp,ref:'inp',defaultValue:'wut'}
_(@props.kids)
.map(({sect},dir)=> @wrap h,dir,path for h in heds for path,heds of sect)
.flatten()
.flatten()
.map(@highlight)
.filter()
.take(50)
.map(reactify)
.value()
highlight: (e)->
return e unless @state.search
got = false
res = reactify.walk e,
()-> null
(s)=>
m = s.split @state.search
return [s] unless m[1]?
lit = gn:'span',c:[@state.search],ga:style:background: '#ff6'
got = true
[m[0], _.flatten([lit,s] for s in m[1..])...]
({gn,ga,c})->{gn,ga,c:_.flatten c}
res if got

View File

@ -1,71 +0,0 @@
query = require './Async.coffee'
reactify = require './Reactify.coffee'
recl = React.createClass
{div} = React.DOM
module.exports = query {body:'r'}, recl
hash:null
displayName: "TableOfContents"
_click: (id)->
-> if id then document.location.hash = id
componentDidMount: ->
@int = setInterval @checkHash,100
@st = $(window).scrollTop()
# $(window).on 'scroll',@checkScroll
@$headers = $('#toc').children('h1,h2,h3,h4').filter('[id]')
checkScroll: ->
st = $(window).scrollTop()
if Math.abs(@st-st) > 10
hash = null
@st = st
for v in @$headers
continue if v.tagName is undefined
$h = $ v
hst = $h.offset().top-$h.outerHeight(true)+10
if hst < st
hash = $h.attr('id')
if hst > st and hash isnt @hash and hash isnt null
@hash = "#"+hash
document.location.hash = hash
break
checkHash: ->
if document.location.hash?.length > 0 and document.location.hash isnt @hash
hash = document.location.hash.slice(1)
for v in @$headers
$h = $ v
if hash is $h.attr('id')
@hash = document.location.hash
offset = $h.offset().top - $h.outerHeight(true)
setTimeout -> $(window).scrollTop offset
, 10
break
componentWillUnmount: ->
clearInterval @int
collectHeader: ({gn,ga,c})->
if gn and gn[0] is 'h' and parseInt(gn[1]) isnt NaN
ga = _.clone ga
ga.onClick = @_click ga.id
delete ga.id
{gn,ga,c}
parseHeaders: ->
if @props.body.c
for v in @props.body.c
if v.gn is 'div' and v.ga?.id is "toc"
return {
gn:"div"
ga:{className:"toc"}
c:[
{gn:"h1", ga:{className:"t"}, c:["Table of contents"]}
(_.filter v.c.map @collectHeader)...
]}
render: -> reactify @parseHeaders()

View File

@ -1,13 +0,0 @@
Dispatcher = require('flux').Dispatcher
module.exports = _.extend new Dispatcher(), {
handleServerAction: (action) ->
@dispatch
source: 'server'
action: action
handleViewAction: (action) ->
@dispatch
source: 'view'
action: action
}

View File

@ -1,135 +0,0 @@
rend = React.render
$ ->
$body = $('body')
React.initializeTouchEvents(true)
head = React.createFactory require './components/AnchorComponent.coffee'
body = React.createFactory require './components/BodyComponent.coffee'
window.tree.components = require './components/Components.coffee' # sigh
window.tree._basepath = window.urb.util.basepath("/")
window.tree._basepath +=
(window.location.pathname.replace window.tree._basepath, "").split("/")[0]
window.tree.basepath = (path) ->
prefix = window.tree._basepath
if prefix is "/" then prefix = ""
if path[0] isnt "/" then path = "/"+path
_path = prefix + path
if _path.slice(-1) is "/" then _path = _path.slice(0,-1)
_path
window.tree.fragpath = (path) ->
path.replace(/\/$/,'')
.replace(window.tree._basepath,"")
TreeActions = require './actions/TreeActions.coffee'
TreePersistence = require './persistence/TreePersistence.coffee'
frag = window.tree.fragpath window.location.pathname
TreeActions.setCurr frag
TreeActions.loadPath frag,window.tree.body,window.tree.kids
rend (head {}, ""),$('#nav')[0]
rend (body {}, ""),$('#cont')[0]
window.tree.util =
getKeys: (kids) ->
sorted = true
keys = []
for k,v of kids
continue if v.meta?.hide
if not v.meta?.sort? then sorted = false
keys[Number(v.meta?.sort)] = k
if sorted isnt true
keys = _.keys(kids).sort()
else
keys = _.values keys
checkScroll = ->
if $(window).scrollTop() > 20
$('#nav').addClass 'scrolling'
else
$('#nav').removeClass 'scrolling'
setInterval checkScroll, 500
po = {}
po.cm = null
po.lm = null
po.cs = $(window).scrollTop()
po.ls = $(window).scrollTop()
$(document).mousemove (e) -> po.cm = {x:e.pageX, y:e.pageY}
checkMove = ->
if po.lm isnt null and po.cm isnt null
po.cs = $(window).scrollTop()
db = $(window).height()-(po.cs+window.innerHeight)
ds = Math.abs po.cs-po.ls
dx = Math.abs po.cm.x-po.lm.x
dy = Math.abs po.cm.y-po.lm.y
$('#nav').toggleClass 'moving',(dx > 20 or dy > 20 or db < 180)
po.lm = po.cm
po.ls = po.cs
setInterval checkMove,200
so = {}
so.ls = $(window).scrollTop()
so.cs = $(window).scrollTop()
so.w = null
so.$n = $('#nav')
so.$d = $('#nav > div')
so.nh = $('#nav').outerHeight(true)
setSo = ->
so.w = $(window).width()
so.$n = $('#nav')
setInterval setSo,200
$(window).on 'resize', (e) ->
if so.w > 1170
so.$n.removeClass 'm-up m-down m-fixed'
$(window).on 'scroll', (e) ->
so.cs = $(window).scrollTop()
if so.w > 1170
so.$n.removeClass 'm-up m-down m-fixed'
if so.w < 1170
dy = so.ls-so.cs
so.$d.removeClass 'focus'
if so.cs <= 0
so.$n.removeClass 'm-up'
so.$n.addClass 'm-down m-fixed'
return
if so.$n.hasClass 'm-fixed' and
so.w < 1024
so.$n.css left:-1*$(window).scrollLeft()
if dy > 0
if not so.$n.hasClass 'm-down'
so.$n.removeClass('m-up').addClass 'm-down'
top = so.cs-so.nh
if top < 0 then top = 0
so.$n.offset top:top
if so.$n.hasClass('m-down') and
not so.$n.hasClass('m-fixed') and
so.$n.offset().top >= so.cs
so.$n.addClass 'm-fixed'
so.$n.attr {style:''}
if dy < 0
if not so.$n.hasClass 'm-up'
so.$n.removeClass('m-down m-fixed').addClass 'm-up'
so.$n.attr {style:''}
top = so.cs
sto = so.$n.offset().top
if top < 0 then top = 0
if top > sto and top < sto+so.nh then top = sto
so.$n.offset top:top
so.ls = so.cs

View File

@ -1,27 +0,0 @@
{
"name": "tree",
"version": "0.0.0",
"description": "urbit tree browser",
"main": "main.js",
"dependencies": {
"classnames": "^2.1.3",
"coffeeify": "~1.0.0",
"flux": "~2.0.1",
"react": "~0.12.2",
"react-tap-event-plugin": "0.1.4"
},
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "https://github.com/urbit/tree"
},
"author": "galen wolfe-pauly",
"license": "ISC",
"bugs": {
"url": "https://github.com/urbit/tree/issues"
},
"homepage": "https://github.com/urbit/tree"
}

View File

@ -1,20 +0,0 @@
dedup = {} # XX wrong layer
module.exports =
get: (path,query="no-query",cb) ->
url = "#{window.tree.basepath(path)}.json?q=#{@encode query}"
return if dedup[url]
dedup[url] = true
$.get url, {}, (data) -> if cb then cb null,data
encode: (obj)->
delim = (n)-> Array(n+1).join('_') || '.'
_encode = (obj)->
if typeof obj isnt 'object'
return [0,obj]
dep = 0
sub = for k,v of obj
[_dep,res] = _encode v
dep = _dep if _dep > dep
k+(delim _dep)+res if res?
dep++
[dep, sub.join delim dep]
(_encode obj)[1]

View File

@ -1,130 +0,0 @@
EventEmitter = require('events').EventEmitter
MessageDispatcher = require '../dispatcher/Dispatcher.coffee'
clog = console.log.bind(console)
_tree = {}
_data = {}
_curr = ""
QUERIES = {body:'r', head:'r', snip:'r', sect:'j', meta:'j'}
TreeStore = _.extend EventEmitter.prototype, {
addChangeListener: (cb) -> @on 'change', cb
removeChangeListener: (cb) -> @removeListener "change", cb
emitChange: -> @emit 'change'
pathToArr: (_path) -> _path.split "/"
fulfill: (path,query) ->
if path is "/" then path = ""
@fulfillAt (@getTree path.split '/'),path,query
fulfillAt: (tree,path,query)->
data = @fulfillLocal path, query
have = _data[path]
if have?
for k,t of query when QUERIES[k]
if t isnt QUERIES[k] then throw TypeError "Wrong query type: #{k}, '#{t}'"
data[k] = have[k]
if query.kids
if have.kids is false
data.kids = {}
else for k,sub of tree
data.kids ?= {}
data.kids[k] = @fulfillAt sub, path+"/"+k, query.kids
data unless _.isEmpty data
fulfillLocal: (path, query)->
data = {}
if query.path then data.path = path
if query.name then data.name = path.split("/").pop()
if query.sein then data.sein = @getPare path
if query.next then data.next = @getNext path
if query.prev then data.prev = @getPrev path
data
setCurr: (path) -> _curr = path
getCurr: -> _curr
loadPath: (path,data) ->
@loadValues (@getTree (path.split '/'),true), path, data
loadValues: (tree,path,data) ->
old = _data[path] ? {}
for k of data when QUERIES[k]
old[k] = data[k]
for k,v of data.kids
tree[k] ?= {}
@loadValues tree[k], path+"/"+k, v
if data.kids && _.isEmpty data.kids
old.kids = false
_data[path] = old
getSiblings: (path=_curr)->
curr = path.split("/")
curr.pop()
if curr.length isnt 0
@getTree curr
else
{}
getTree: (_path,make=false) ->
tree = _tree
for sub in _path
if not tree[sub]?
if not make then return null
tree[sub] = {}
tree = tree[sub]
tree
getPrev: (path=_curr)->
sibs = _.keys(@getSiblings path).sort()
if sibs.length < 2
null
else
par = path.split "/"
key = par.pop()
ind = sibs.indexOf key
win = if ind-1 >= 0 then sibs[ind-1] else sibs[sibs.length-1]
par.push win
par.join "/"
getNext: (path=_curr)->
sibs = _.keys(@getSiblings path).sort()
if sibs.length < 2
null
else
par = path.split "/"
key = par.pop()
ind = sibs.indexOf key
win = if ind+1 < sibs.length then sibs[ind+1] else sibs[0]
par.push win
par.join "/"
getPare: (path=_curr)->
_path = @pathToArr path
if _path.length > 1
_path.pop()
_path = _path.join "/"
if _path is "" then _path = "/"
_path
else
null
}
TreeStore.dispatchToken = MessageDispatcher.register (payload) ->
action = payload.action
switch action.type
when 'path-load'
TreeStore.loadPath action.path,action.data
TreeStore.emitChange()
when 'set-curr'
TreeStore.setCurr action.path
TreeStore.emitChange()
module.exports = TreeStore

View File

@ -1,12 +0,0 @@
# installing
`npm install`
# building
in `src/js/`:
`watchify -v -t coffeeify -o main.js main.coffee`
in `src/css/`:
`stylus -w main.styl`