Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: yourcelf/dotstorm
base: c2782cdc87
...
head fork: yourcelf/dotstorm
compare: d036b8bbeb
Checking mergeability… Don't worry, you can still create the pull request.
  • 3 commits
  • 6 files changed
  • 0 commit comments
  • 1 contributor
View
2  Cakefile
@@ -7,7 +7,7 @@ option '-p', "--port [#{config.port}]", 'port the server runs on'
option '-h', "--host [#{config.host}]", 'base server name'
option '-s', "--secret [#{config.secret}]", 'session secret'
-task 'runserver', 'Run the server, watching for changes.', (options) ->
+task 'runserver', 'Run the server.', (options) ->
server = require './lib/server'
server.start
host: options.host or config.host
View
46 assets/css/style.styl
@@ -229,35 +229,12 @@ a:link.cta, a:visited.cta, a.cta
width: 100%
height: 100%
-.idea-browser
- clear: both
- .sort-link
- float: left
- .sizes
- height: 2em
- a.resize
- display: inline-block
- width: 1em
- height: 1em
- cursor: pointer
- border: 1px solid #333
- background-color: rgba(100, 100, 0, 0.5)
- margin-right: 0.2em
- &.small
- position: relative
- top: 0.5em
- width: 1em
- height: 1em
- &.medium
- position: relative
- top: 0.25em
- width: 1.5em
- height: 1.5em
- &.large
- position: relative
- top: 0em
- width: 2em
- height: 2em
+.sort.active
+ font-weight: bold
+ &:before
+ content: "↓"
+ &.reverse:before
+ content: "↑"
.smallIdea
cursor: pointer
@@ -338,8 +315,17 @@ a:link.cta, a:visited.cta, a.cta
transform: rotate(-2deg)
opacity: 0.7
z-index: 10
- &:hover, &.hovered
+ .border
+ width: 118px
+ height: 118px
+ &.hovered
outline: 3px solid orange
+ &.leftside .border
+ border-left: 6px solid orange
+ width: 112px
+ &.rightside .border
+ border-right: 6px solid orange
+ width: 112px
.vote-widget
display: inline-block
View
326 assets/js/frontend.coffee
@@ -18,6 +18,13 @@ if typeof console == 'undefined'
if not window.ds?
ds = window.ds = {}
+getQueryStrParameterByName = (name) ->
+ # Get url query parameter by name.
+ # http://stackoverflow.com/questions/901115/get-query-string-values-in-javascript
+ match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search)
+ return match && decodeURIComponent(match[1].replace(/\+/g, ' '))
+
+
class ds.Intro extends Backbone.View
#
# A front-page form for opening or creating new dotstorms.
@@ -66,7 +73,7 @@ class ds.Topic extends Backbone.View
@model.on "change", @render
render: =>
- console.log "render topic"
+ console.debug "render topic"
@$el.html @template
name: @model.get("name")
topic: @model.get("topic") or "Click to edit topic..."
@@ -290,13 +297,14 @@ class ds.EditIdea extends Backbone.View
}
if ideaIsNew
attrs.creator = ds.users?.self?.user_id
+ attrs.order = ds.ideas.length
@idea.save attrs,
success: (model) ->
if ideaIsNew
ds.ideas.add(model)
ds.app.navigate "/d/#{ds.model.get("slug")}/#{model.id}", trigger: true
error: (model, err) ->
- console.log(err)
+ console.error(err)
str = if err.error? then err.error else err
flash "error", "Error saving: #{str}"
@@ -372,8 +380,8 @@ class ds.ShowIdeas extends Backbone.View
template: _.template $("#dotstormShowIdeas").html() or ""
events:
'click .sizes a': 'resize'
- 'click .sort-link': 'softNav'
'click .add-link': 'softNav'
+ 'click .sort': 'handleSort'
'click .tag': 'toggleTag'
'mousedown .smallIdea': 'startDrag'
'mousemove .smallIdea': 'continueDrag'
@@ -388,7 +396,7 @@ class ds.ShowIdeas extends Backbone.View
large: 238
initialize: (options) ->
- console.log 'Dotstorm: NEW DOTSTORM'
+ console.debug 'Dotstorm: NEW DOTSTORM'
@dotstorm = options.model
# ID of a single note to show, popped out
@showId = options.showId
@@ -399,27 +407,70 @@ class ds.ShowIdeas extends Backbone.View
@smallIdeaViews = {}
@dotstorm.on "change", =>
- console.log "Dotstorm: dotstorm changed"
+ console.debug "Dotstorm: dotstorm changed"
@renderTopic()
@groups.on "change", =>
- console.log "Dotstorm: groups changed"
+ console.debug "Dotstorm: groups changed"
@renderGroups()
@groups.on "remove", =>
- console.log "Dotstorm: group deleted"
+ console.debug "Dotstorm: group deleted"
@renderGroups()
@groups.on "add", =>
- console.log "Dotstorm: group added"
+ console.debug "Dotstorm: group added"
@renderGroups()
@ideas.on "add", =>
- console.log "Dotstorm: idea added"
+ console.debug "Dotstorm: idea added"
@renderGroups()
-
+ @ideas.on "sort", =>
+ console.debug "Dotstorm: sorted", @sort
+ @renderGroups()
+ @ideas.on "change:order", =>
+ console.log "Dostorm: sorted", @sort
+ if @orderChangeTimeout
+ clearTimeout @orderChangeTimeout
+ @orderChangeTimeout = setTimeout (=> @renderGroups()), 200
$(window).on "mouseup", @stopDrag
softNav: (event) =>
ds.app.navigate $(event.currentTarget).attr("href"), trigger: true
return false
+ setSort: (sort, options) =>
+ @sort = sort or getQueryStrParameterByName('sort')
+ switch @sort
+ when "date"
+ @ideas.comparator = (model) -> return model.get("created")
+ when "-date"
+ @ideas.comparator = (model) -> return -model.get("created")
+ when "votes"
+ @ideas.comparator = (model) -> return model.get("votes")?.length or 0
+ when "-votes"
+ @ideas.comparator = (model) -> return -(model.get("votes")?.length or 0)
+ when "-order"
+ @ideas.comparator = (model) -> return -(model.get("order") or 0)
+ else
+ @ideas.comparator = (model) -> return model.get("order")
+ @ideas.sort()
+ @ideas.trigger "sort" unless options?.silent
+ @$(".sort").removeClass("active reverse")
+ if @sort?.substring(0, 1) == "-"
+ sort = @sort.substring(1)
+ reverse = true
+ else
+ sort = @sort
+ reverse = false
+ target = @$("a[data-sort=\"#{sort}\"]")
+ target.addClass("active")
+ if reverse then target.addClass("reverse")
+ ds.app.navigate window.location.pathname + "?sort=#{@sort}", trigger: false
+
+ handleSort: (event) =>
+ sort = $(event.currentTarget).attr("data-sort")
+ if @sort? and @sort == sort
+ sort = "-#{sort}"
+ @setSort sort
+ return false
+
sortGroups: =>
grouped = {}
for group in @groups.models
@@ -445,6 +496,7 @@ class ds.ShowIdeas extends Backbone.View
model_order.push(idea)
group_set.models.push(idea)
count += 1
+ group_set.models = _.sortBy group_set.models, @ideas.comparator
group_order.push(group_set)
for idea in ungrouped
if count > 0
@@ -452,7 +504,9 @@ class ds.ShowIdeas extends Backbone.View
idea.prev.next = idea
model_order.push(idea)
count += 1
+ ungrouped = _.sortBy ungrouped, @ideas.comparator
group_order.push({ models: ungrouped })
+ group_order = _.sortBy group_order, (g) => @ideas.comparator(g.models[0])
return group_order
showBig: (model) =>
@@ -521,22 +575,21 @@ class ds.ShowIdeas extends Backbone.View
return false
render: =>
- console.log "Dotstorm: RENDER DOTSTORM"
+ console.debug "Dotstorm: RENDER DOTSTORM"
@$el.html @template
sorting: true
slug: @model.get("slug")
tags: @getTags()
@$el.addClass "sorting"
-
@renderTopic()
- @renderGroups()
+ @setSort() #@renderGroups()
@renderOverlay()
renderTopic: =>
@$(".topic").html new ds.Topic(model: @dotstorm).render().el
renderGroups: =>
- console.log "render groups"
+ console.debug "render groups"
group_order = @sortGroups()
@$("#showIdeas").html("")
if @ideas.length == 0
@@ -571,138 +624,193 @@ class ds.ShowIdeas extends Backbone.View
moveNote: (event) =>
pos = @getPosition(event)
- @active.css
+ @dragState.active.css
position: "absolute"
- left: pos.x + @mouseOffset.x + "px"
- top: pos.y + @mouseOffset.y + "px"
- for dim in @noteDims
- if dim.left < pos.x < dim.left + dim.width and dim.top < pos.y < dim.top + dim.height
- $(dim.el).addClass("hovered")
- else
- $(dim.el).removeClass("hovered")
+ left: pos.x + @dragState.mouseOffset.x + "px"
+ top: pos.y + @dragState.mouseOffset.y + "px"
+ for dim in @dragState.noteDims
+ if dim.el[0] == @dragState.active[0]
+ continue
+ dim.el.removeClass("hovered leftside rightside")
+ if dim.top < pos.y < dim.top + dim.height
+ if dim.left < pos.x < dim.left + dim.width * 0.2
+ dim.el.addClass("leftside")
+ if dim.left + dim.width * 0.2 < pos.x < dim.left + dim.width * 0.8
+ dim.el.addClass("hovered")
+ if dim.left + dim.width * 0.8 < pos.x < dim.left + dim.width
+ dim.el.addClass("rightside")
return false
startDrag: (event) =>
event.preventDefault()
event.stopPropagation()
- @maybeClick = true
- setTimeout =>
- @maybeClick = false
- , 400
- $(event.currentTarget).addClass("active")
- @mouseIsDown = true
- @active = $(event.currentTarget)
- @placeholder = $("<div class='smallIdea'></div>").css
- width: @active.width() + "px",
- height: @active.height() + "px"
-
- pos = @getPosition(event)
- offset = @active.position()
- @mouseOffset =
- x: offset.left - pos.x
- y: offset.top - pos.y
- @noteDims = []
+ active = $(event.currentTarget)
+ active.addClass("active")
+ @dragState = {
+ startTime: new Date().getTime()
+ startPos: @getPosition(event)
+ active: active
+ offset: active.position()
+ noteDims: []
+ placeholder: $("<div></div>").css
+ float: "left"
+ width: active.width() + "px"
+ height: active.height() + "px"
+ dropTagrets: []
+ }
+ @dragState.mouseOffset =
+ x: @dragState.offset.left - @dragState.startPos.x
+ y: @dragState.offset.top - @dragState.startPos.y
for note in @$(".smallIdea")
$n = $(note)
dims = $n.offset()
dims.width = $n.width()
dims.height = $n.height()
dims.el = $n
- @noteDims.push(dims)
- @active.before(@placeholder)
+ @dragState.noteDims.push(dims)
+ @dragState.active.before(@dragState.placeholder)
@moveNote(event)
return false
continueDrag: (event) =>
event.preventDefault()
event.stopPropagation()
- if @mouseIsDown
+ if @dragState
@moveNote(event)
return false
+ checkForClick: (event) =>
+ pos = @getPosition(event)
+ distance = Math.sqrt(
+ Math.pow(pos.x - @dragState.startPos.x, 2) +
+ Math.pow(pos.y - @dragState.startPos.y, 2)
+ )
+ elapsed = new Date().getTime() - @dragState.startTime
+ return distance < 20 and elapsed < 400
+
stopDrag: (event) =>
event.preventDefault()
event.stopPropagation()
- $(event.currentTarget).removeClass("active")
+
+ @dragState?.placeholder?.remove()
# reset drag UI...
- @placeholder?.remove()
- @mouseIsDown = false
- @noteDims = []
- @mouseOffset = null
- unless @active?
+ unless @dragState? and @dragState.active?
return
-
- @active.css
+ @dragState.active.removeClass("active")
+ @dragState.active.css
position: "relative"
left: 0
top: 0
- @active = null
+ leftside = @$(".leftside")
+ rightside = @$(".rightside")
hovered = @$(".hovered")
- hovered.removeClass("hovered")
-
- dragged = $(event.currentTarget)
- source = @ideas.get dragged.attr("data-id")
+ @$(".smallIdea").removeClass("leftside rightside hovered")
- if @maybeClick == true
- @showBig(source)
+ sourceModel = @ideas.get @dragState.active.attr("data-id")
+ unless sourceModel?
+ @dragState = null
return
- unless source?
+
+ if @checkForClick(event)
+ @showBig(sourceModel)
+ @dragState = null
return
- if hovered[0]? and hovered[0] != event.currentTarget
- #
- # Are we being dragged into a group?
- #
- target = @ideas.get hovered.attr("data-id")
+
+ droppable = hovered[0] or leftside[0] or rightside[0]
+ groupParent = @dragState.active.parents(".group:first")
+ if droppable?
+ targetModel = @ideas.get droppable.getAttribute("data-id")
targetGroup = null
for group in @groups.models
unless group?
continue
- if group.containsIdea(target.id)
+ if group.containsIdea(targetModel.id)
targetGroup = group
- # Remove old group, if any
- if group.removeIdea(source.id, {silent: true}) and group.get("ideas").length > 0
- group.save null,
- error: (model, err) =>
- flash "error", "Error saving group: #{err}"
- else if group.get("ideas").length == 0
- group.destroy
- error: (model, err) =>
- flash "error", "Error removing group: #{err}"
-
- unless targetGroup?
- targetGroup = new IdeaGroup dotstorm_id: @dotstorm.id
-
- ideas = targetGroup.get("ideas") or []
- targetGroup.addIdeas([source.id, target.id], silent: true)
- if targetGroup.isNew()
- @groups.add(targetGroup, {silent: true})
- targetGroup.save null,
- error: (model, err) =>
- flash "error", "Error saving group: #{err}"
- else
- #
+ break
+ if not targetGroup?
+ if hovered[0]?
+ targetGroup = new IdeaGroup dotstorm_id: @dotstorm.id
+ targetGroup.addIdeas [targetModel.id], silent: true
+ else if groupParent[0]?
+ @removeFromGroup(sourceModel, @groups.get(groupParent.attr("data-id")))
+ if targetGroup?
+ @joinGroup sourceModel, targetGroup
+ if leftside[0]?
+ @putModelLeftOf sourceModel, targetModel
+ else
+ @putModelRightOf sourceModel, targetModel
+ else if groupParent[0]?
# Are we being dragged out of all groups?
- #
- groupParent = dragged.parents(".group:first")
- if groupParent.length == 1 and groupParent.attr("data-id")?
- pos = @getPosition(event)
- dims = groupParent.offset()
- dims.width = groupParent.width()
- dims.height = groupParent.height()
- unless dims.left < pos.x < dims.left + dims.width and dims.top < pos.y < dims.top + dims.height
- # We've been dragged out. Extricate ourselves from our group.
- group = @groups.get(groupParent.attr("data-id"))
- if group.removeIdea(source.id, silent: true) and group.get("ideas").length > 0
- group.save null,
- error: (model, err) =>
- flash "error", "Error saving group: #{err}"
- else if group.get("ideas").length == 0
- group.destroy
- error: (model, err) =>
- flash "error", "Error removing group: #{err}"
+ pos = @getPosition(event)
+ dims = groupParent.offset()
+ dims.width = groupParent.width()
+ dims.height = groupParent.height()
+ unless dims.left < pos.x < dims.left + dims.width and dims.top < pos.y < dims.top + dims.height
+ # We've been dragged out. Extricate ourselves from our group.
+ @removeFromGroup(sourceModel, @groups.get(groupParent.attr("data-id")))
+ @dragState = null
return false
+ putModelLeftOf: (sourceModel, targetModel) =>
+ console.debug "putModelLeftOf"
+ newOrder = []
+ for model in @ideas.models
+ if model == targetModel
+ newOrder.push(sourceModel)
+ newOrder.push(targetModel)
+ else if model != sourceModel
+ newOrder.push(model)
+ for i in [0...newOrder.length]
+ newOrder[i].save("order", i, silent: true)
+ @ideas.sort()
+ @ideas.trigger "sort"
+
+ putModelRightOf: (sourceModel, targetModel) =>
+ console.debug "putModelRightOf"
+ newOrder = []
+ for model in @ideas.models
+ if model == targetModel
+ newOrder.push(targetModel)
+ newOrder.push(sourceModel)
+ else if model != sourceModel
+ newOrder.push(model)
+ for i in [0...newOrder.length]
+ newOrder[i].set("order", i, silent: true)
+ @ideas.sort()
+ @ideas.trigger "sort"
+
+ removeFromGroup: (sourceModel, group) =>
+ if group.removeIdea(sourceModel.id, silent: true) and group.get("ideas").length > 0
+ group.save null,
+ error: (model, err) =>
+ flash "error", "Error saving group: #{err}"
+ else if group.get("ideas").length == 0
+ group.destroy
+ error: (model, err) =>
+ flash "error", "Error removing group: #{err}"
+
+ joinGroup: (sourceModel, targetGroup) =>
+ for group in @groups.models
+ unless group?
+ continue
+ if group.removeIdea(sourceModel.id, {silent: true}) and group.get("ideas").length > 0
+ group.save null,
+ error: (model, err) =>
+ flash "error", "Error saving group: #{err}"
+ else if group.get("ideas").length == 0
+ group.destroy
+ error: (model, err) =>
+ flash "error", "Error removing group: #{err}"
+
+ ideas = targetGroup.get("ideas") or []
+ targetGroup.addIdeas([sourceModel.id], silent: true)
+ if targetGroup.isNew()
+ @groups.add(targetGroup, {silent: true})
+ targetGroup.save null,
+ error: (model, err) =>
+ flash "error", "Error saving group: #{err}"
+
class ds.ShowIdeaSmall extends Backbone.View
template: _.template $("#dotstormSmallIdea").html() or ""
initialize: (options) ->
@@ -714,7 +822,7 @@ class ds.ShowIdeaSmall extends Backbone.View
@model.on "change:description", @render
render: =>
- console.log "render small", @model.id
+ console.debug "render small", @model.id
args = _.extend
tags: ""
description: ""
@@ -770,7 +878,7 @@ class ds.ShowIdeaBig extends Backbone.View
@model.on "change:drawing", @render
render: =>
- console.log "render big"
+ console.debug "render big"
args = _.extend {
tags: ""
description: ""
@@ -860,7 +968,7 @@ class ds.VoteWidget extends Backbone.View
@undelegateEvents()
render: =>
- console.log "render votewidget", @idea.id
+ console.debug "render votewidget", @idea.id
@$el.addClass("vote-widget")
votes = @idea.get("votes") or []
@$el.html @template
@@ -1061,7 +1169,7 @@ ds.socket.on 'connect', ->
ds.client = new Client(ds.socket)
Backbone.history.start pushState: true
ds.socket.on 'users', (data) ->
- console.log "users", data
+ console.debug "users", data
ds.users = new ds.UsersView
users: data
url: "#{window.location.protocol}//#{window.location.host}/d/#{ds.model.get("slug")}/"
@@ -1075,7 +1183,7 @@ ds.socket.on 'connect', ->
ds.users?.setUser(user)
ds.socket.on 'backbone', (data) ->
- console.log 'backbone sync', data
+ console.debug 'backbone sync', data
switch data.signature.collectionName
when "Idea"
switch data.signature.method
View
10 assets/js/models.coffee
@@ -27,11 +27,11 @@ class Idea extends Backbone.Model
cleaned = @getTags(attrs.tags).join(", ")
if cleaned != attrs.tags
@set "tags", cleaned, silent: true
-# if not attrs.imageVersion?
-# @set "imageVersion", 0, silent: true
-# if not attrs.created?
-# @set "created", new Date().getTime(), silent: true
-# @set "modified", new Date().getTime(), silent: true
+ if not attrs.imageVersion?
+ @set "imageVersion", 0, silent: true
+ if not attrs.created?
+ @set "created", new Date().getTime(), silent: true
+ @set "modified", new Date().getTime(), silent: true
return
getThumbnailURL: (size) =>
View
16 lib/ideacanvas2image.coffee
@@ -133,12 +133,18 @@ draw = (idea, callback) ->
mkthumbs = (idea, callback) ->
# Create thumbnail images for the given idea.
if idea.get("background")? and idea.get("drawing")?
- clearDir BASE_PATH + path.dirname(idea.getThumbnailURL('small')), (err) ->
- if (err) then return callback?(err)
- draw idea, (err) ->
- if (err) then return callback?(err)
- callback(null)
+ path.exists BASE_PATH + idea.getThumbnailURL('small'), (exists) ->
+ unless exists
+ clearDir BASE_PATH + path.dirname(idea.getThumbnailURL('small')), (err) ->
+ if (err) then return callback?(err)
+ draw idea, (err) ->
+ if (err) then return callback?(err)
+ callback(null)
+ else
+ callback()
+ logger.debug("skipping thumbnail; already exists")
else
+ callback()
logger.debug("skipping thumbnail; empty model")
remove = (model) ->
View
6 views/dotstorm.jade
@@ -57,6 +57,12 @@ script#dotstormShowIdeas(type='text/template')
div.topic
div.tag-links
| Order by
+ a.sort(href='?sort=drop', data-sort='drop') drop
+ |,
+ a.sort(href='?sort=votes', data-sort='votes') votes
+ |,
+ a.sort(href='?sort=date', data-sort='date') date
+ br
<% if (tags) { %>
| Filter by tag:
| <% for (var tag in tags) { %>

No commit comments for this range

Something went wrong with that request. Please try again.