Changeset - 3c997bc6d380
[Not reviewed]
default
0 11 1
Drew Perttula - 7 years ago 2018-05-24 06:54:58
drewp@bigasterisk.com
fix some coffee lint
Ignore-this: 1a988be1598dda76dd2fefca3b499aa0
12 files changed with 296 insertions and 153 deletions:
0 comments (0 inline, 0 general)
coffeelint.json
Show inline comments
 
new file 100644
 
{
 
  "arrow_spacing": {
 
    "level": "ignore"
 
  },
 
  "braces_spacing": {
 
    "level": "ignore",
 
    "spaces": 0,
 
    "empty_object_spaces": 0
 
  },
 
  "camel_case_classes": {
 
    "level": "error"
 
  },
 
  "coffeescript_error": {
 
    "level": "error"
 
  },
 
  "colon_assignment_spacing": {
 
    "level": "ignore",
 
    "spacing": {
 
      "left": 0,
 
      "right": 0
 
    }
 
  },
 
  "cyclomatic_complexity": {
 
    "level": "ignore",
 
    "value": 10
 
  },
 
  "duplicate_key": {
 
    "level": "error"
 
  },
 
  "empty_constructor_needs_parens": {
 
    "level": "ignore"
 
  },
 
  "ensure_comprehensions": {
 
    "level": "warn"
 
  },
 
  "eol_last": {
 
    "level": "ignore"
 
  },
 
  "indentation": {
 
    "value": 2,
 
    "level": "error"
 
  },
 
  "line_endings": {
 
    "level": "ignore",
 
    "value": "unix"
 
  },
 
  "max_line_length": {
 
    "value": 80,
 
    "level": "error",
 
    "limitComments": true
 
  },
 
  "missing_fat_arrows": {
 
    "level": "ignore",
 
    "is_strict": false
 
  },
 
  "newlines_after_classes": {
 
    "value": 3,
 
    "level": "ignore"
 
  },
 
  "no_backticks": {
 
    "level": "warn"
 
  },
 
  "no_debugger": {
 
    "level": "warn",
 
    "console": false
 
  },
 
  "no_empty_functions": {
 
    "level": "ignore"
 
  },
 
  "no_empty_param_list": {
 
    "level": "ignore"
 
  },
 
  "no_implicit_braces": {
 
    "level": "ignore",
 
    "strict": true
 
  },
 
  "no_implicit_parens": {
 
    "level": "ignore",
 
    "strict": true
 
  },
 
  "no_interpolation_in_single_quotes": {
 
    "level": "ignore"
 
  },
 
  "no_nested_string_interpolation": {
 
    "level": "warn"
 
  },
 
  "no_plusplus": {
 
    "level": "ignore"
 
  },
 
  "no_private_function_fat_arrows": {
 
    "level": "warn"
 
  },
 
  "no_stand_alone_at": {
 
    "level": "ignore"
 
  },
 
  "no_tabs": {
 
    "level": "error"
 
  },
 
  "no_this": {
 
    "level": "ignore"
 
  },
 
  "no_throwing_strings": {
 
    "level": "error"
 
  },
 
  "no_trailing_semicolons": {
 
    "level": "error"
 
  },
 
  "no_trailing_whitespace": {
 
    "level": "error",
 
    "allowed_in_comments": false,
 
    "allowed_in_empty_lines": true
 
  },
 
  "no_unnecessary_double_quotes": {
 
    "level": "ignore"
 
  },
 
  "no_unnecessary_fat_arrows": {
 
    "level": "warn"
 
  },
 
  "non_empty_constructor_needs_parens": {
 
    "level": "ignore"
 
  },
 
  "prefer_english_operator": {
 
    "level": "ignore",
 
    "doubleNotLevel": "ignore"
 
  },
 
  "space_operators": {
 
    "level": "ignore"
 
  },
 
  "spacing_after_comma": {
 
    "level": "ignore"
 
  },
 
  "transform_messes_up_line_numbers": {
 
    "level": "warn"
 
  }
 
}
light9/web/coffee_element.coffee
Show inline comments
 
# Polymer seems to need static getters for 'observers' and
 
# 'properties', not just static attributes, though I don't know how it
 
# can even tell the difference.
 
#
 
# This workaround is to use names like '@getter_properties' in the
 
# class then register with this function that fixes them.
 
# 
 
#
 
# Also see http://coffeescript.org/#unsupported-get-set
 
window.coffeeElementSetup = (cls) ->
 
  for attr in ['properties', 'observers']
 
    val = cls['getter_' + attr]
 
    if val?
 
      do (val) ->
 
        Object.defineProperty(cls, attr, {get: ( -> val)})  
 
        Object.defineProperty(cls, attr, {get: ( -> val)})
 
  customElements.define(cls.is, cls)
light9/web/edit-choice.coffee
Show inline comments
 
@@ -40,22 +40,22 @@ window.setupDrop = (senseElem, highlight
 
      console.log(e)
 
    unhighlight()
 

	
 

	
 

	
 
coffeeElementSetup(class EditChoice extends Polymer.Element
 
    @is: "edit-choice",
 
    @getter_properties:
 
        graph: {type: Object, notify: true},
 
        uri: {type: String, notify: true},
 
  @is: "edit-choice",
 
  @getter_properties:
 
    graph: {type: Object, notify: true},
 
    uri: {type: String, notify: true},
 

	
 
    _setUri: (u) ->
 
      @uri = u
 
      @dispatchEvent(new CustomEvent('edited'))
 
  _setUri: (u) ->
 
    @uri = u
 
    @dispatchEvent(new CustomEvent('edited'))
 

	
 
    connectedCallback: ->
 
      super.connectedCallback()
 
      setupDrop(@$.box, @$.box, null, @_setUri.bind(@))
 
  connectedCallback: ->
 
    super.connectedCallback()
 
    setupDrop(@$.box, @$.box, null, @_setUri.bind(@))
 

	
 
    unlink: ->
 
      @_setUri(null)
 
  unlink: ->
 
    @_setUri(null)
 
)
light9/web/graph.coffee
Show inline comments
 
@@ -25,13 +25,15 @@ class Handler
 
  constructor: (@func, @label) ->
 
    @patterns = [] # s,p,o,g quads that should trigger the next run
 
    @innerHandlers = [] # Handlers requested while this one was running
 
  
 
class AutoDependencies
 
  constructor: () ->
 
    @handlers = new Handler(null) # tree of all known Handlers (at least those with non-empty patterns). Top node is not a handler.
 
    # tree of all known Handlers (at least those with non-empty
 
    # patterns). Top node is not a handler.
 
    @handlers = new Handler(null)
 
    @handlerStack = [@handlers] # currently running
 
    
 
  runHandler: (func, label) ->
 
    # what if we have this func already? duplicate is safe?
 

	
 
    if not label?
 
@@ -124,13 +126,13 @@ class AutoDependencies
 
    #  console.trace('read outside runHandler')
 

	
 
class window.SyncedGraph
 
  # Main graph object for a browser to use. Syncs both ways with
 
  # rdfdb. Meant to hide the choice of RDF lib, so we can change it
 
  # later.
 
  # 
 
  #
 
  # Note that _applyPatch is the only method to write to the graph, so
 
  # it can fire subscriptions.
 

	
 
  constructor: (@patchSenderUrl, @prefixes, @setStatus) ->
 
    # patchSenderUrl is the /syncedGraph path of an rdfdb server.
 
    # prefixes can be used in Uri(curie) calls.
 
@@ -148,13 +150,13 @@ class window.SyncedGraph
 
    if @graph?
 
      @_applyPatch({addQuads: [], delQuads: @graph.getQuads()})
 

	
 
    # if we had a Store already, this lets N3.Store free all its indices/etc
 
    @graph = N3.Store()
 
    @_addPrefixes(@prefixes)
 
    @cachedFloatValues = new Map();
 
    @cachedFloatValues = new Map()
 

	
 
  _clearGraphOnNewConnection: -> # must not send a patch to the server!
 
    log('graph: clearGraphOnNewConnection')
 
    @clearGraph()
 
    log('graph: clearGraphOnNewConnection done')
 
      
 
@@ -185,20 +187,20 @@ class window.SyncedGraph
 
    parseFloat(literal.value)
 

	
 
  loadTrig: (trig, cb) -> # for debugging
 
    patch = {delQuads: [], addQuads: []}
 
    parser = N3.Parser()
 
    parser.parse trig, (error, quad, prefixes) =>
 
                  if error
 
                    throw new Error(error)
 
                  if (quad)
 
                    patch.addQuads.push(quad)
 
                  else
 
                    @_applyPatch(patch)
 
                    @_addPrefixes(prefixes)
 
                    cb() if cb
 
      if error
 
        throw new Error(error)
 
      if (quad)
 
        patch.addQuads.push(quad)
 
      else
 
        @_applyPatch(patch)
 
        @_addPrefixes(prefixes)
 
        cb() if cb
 
                    
 
  quads: () -> # for debugging
 
    [q.subject, q.predicate, q.object, q.graph] for q in @graph.getQuads()
 

	
 
  applyAndSendPatch: (patch) ->
 
    console.time('applyAndSendPatch')
 
@@ -220,17 +222,17 @@ class window.SyncedGraph
 
          throw new Error("doesn't look like a proper Quad")
 
        if not q.subject.id or not q.graph.id? or not q.predicate.id?
 
          throw new Error("corrupt patch: #{JSON.stringify(q)}")
 
    
 
  _applyPatch: (patch) ->
 
    # In most cases you want applyAndSendPatch.
 
    # 
 
    #
 
    # This is the only method that writes to @graph!
 
    @cachedFloatValues.clear()
 
    for quad in patch.delQuads
 
      #log("remove #{JSON.stringify(quad)}")      
 
      #log("remove #{JSON.stringify(quad)}")
 
      did = @graph.removeQuad(quad)
 
      #log("removed: #{did}")
 
    for quad in patch.addQuads
 
      @graph.addQuad(quad)
 
    #log('applied patch locally', patchSizeSummary(patch))
 
    @_autoDeps.graphChanged(patch)
 
@@ -320,17 +322,19 @@ class window.SyncedGraph
 
        
 
      @_autoDeps.askedFor(current, null, null, null) # a little loose
 

	
 
      firsts = @graph.getQuads(current, RDF + 'first', null)
 
      rests = @graph.getQuads(current, RDF + 'rest', null)
 
      if firsts.length != 1
 
        throw new Error("list node #{current} has #{firsts.length} rdf:first edges")
 
        throw new Error(
 
          "list node #{current} has #{firsts.length} rdf:first edges")
 
      out.push(firsts[0].object)
 

	
 
      if rests.length != 1
 
        throw new Error("list node #{current} has #{rests.length} rdf:rest edges")
 
        throw new Error(
 
          "list node #{current} has #{rests.length} rdf:rest edges")
 
      current = rests[0].object
 
    
 
    return out
 

	
 
  contains: (s, p, o) ->
 
    @_autoDeps.askedFor(s, p, o, null)
 
@@ -347,13 +351,13 @@ class window.SyncedGraph
 
        results.push(uri)
 
        if results.length >= howMany
 
          return results
 
    throw new Error("can't make sequential uri with base #{base}")
 

	
 
  nextNumberedResource: (base) ->
 
    @nextNumberedResources(base, 1)[0]       
 
    @nextNumberedResources(base, 1)[0]
 

	
 
  contextsWithPattern: (s, p, o) ->
 
    @_autoDeps.askedFor(s, p, o, null)
 
    ctxs = []
 
    for q in @graph.getQuads(s, p, o)
 
      ctxs.push(q.graph)
light9/web/graph_test.coffee
Show inline comments
 
@@ -47,13 +47,13 @@ describe 'SyncedGraph', ->
 
      hand = ->
 
        called++
 
        graph.uriValue(A1, A2)
 
      graph.runHandler(hand, 'run')
 
      graph.applyAndSendPatch({
 
        delQuads: [quad(A1, A2, A3)], addQuads: [quad(A1, A2, A4)]})
 
      assert.equal(2, called) 
 
      assert.equal(2, called)
 

	
 
    it 'notices new queries a handler makes upon rerun', ->
 
      called = 0
 
      objsFound = []
 
      hand = ->
 
        called++
 
@@ -77,13 +77,13 @@ describe 'SyncedGraph', ->
 
        called++
 
        graph.uriValue(A1, A2)
 
        throw new Error('this test handler throws an error')
 
      graph.runHandler(hand, 'run')
 
      graph.applyAndSendPatch({
 
        delQuads: [quad(A1, A2, A3)], addQuads: [quad(A1, A2, A4)]})
 
      assert.equal(2, called) 
 
      assert.equal(2, called)
 

	
 
    describe 'works with nested handlers', ->
 

	
 
      innerResults = []
 
      inner = ->
 
        console.log('\nninnerfetch')
 
@@ -197,33 +197,33 @@ describe 'SyncedGraph', ->
 

	
 
      describe 'items', ->
 
        it 'when the list order changes', (done) ->
 
          values = []
 
          successes = 0
 
          hand = ->
 
            try 
 
            try
 
              head = graph.uriValue(U('x'), U('y'))
 
            catch
 
              # graph goes empty between clearGraph and loadTrig
 
              return
 
            values.push(graph.items(head))
 
            successes++
 
          graph.clearGraph()
 
          graph.loadTrig "
 
            @prefix : <http://example.com/> .
 
            :ctx { :x :y (:a1 :a2 :a3) } .
 
          ", () ->
 
            graph.runHandler(hand, 'run')
 
            graph.clearGraph()
 
            graph.loadTrig "
 
             graph.runHandler(hand, 'run')
 
             graph.clearGraph()
 
             graph.loadTrig "
 
              @prefix : <http://example.com/> .
 
              :ctx { :x :y (:a1 :a3 :a2) } .
 
            ", () ->
 
              assert.deepEqual([[A1, A2, A3], [A1, A3, A2]], values)
 
              assert.equal(2, successes)
 
              done()
 
               assert.deepEqual([[A1, A2, A3], [A1, A3, A2]], values)
 
               assert.equal(2, successes)
 
               done()
 
  
 
      describe 'contains', ->
 
        it 'when a new triple is added', ->
 
          values = []
 
          hand = -> values.push(graph.contains(A1, A1, A1))
 
          graph.runHandler(hand, 'run')
light9/web/rdfdbclient.coffee
Show inline comments
 
@@ -22,40 +22,41 @@ toJsonPatch = (jsPatch, cb) ->
 
    writer.addQuads(jsPatch.addQuads)
 
    writer.end((err, result) ->
 
      out.patch.adds = result
 
      cb())
 
    
 
  async.parallel([writeDels, writeAdds], (err) ->
 
      cb(JSON.stringify(out))
 
    )
 
    cb(JSON.stringify(out))
 
  )
 

	
 
parseJsonPatch = (jsonPatch, cb) ->
 
  # note response cb doesn't have an error arg.
 
  input = JSON.parse(jsonPatch)
 
  patch = {delQuads: [], addQuads: []}
 

	
 
  parseAdds = (cb) =>
 
    parser = N3.Parser()
 
    parser.parse input.patch.adds, (error, quad, prefixes) =>
 
                  if (quad)
 
                    patch.addQuads.push(quad)
 
                  else
 
                    cb()
 
      if (quad)
 
        patch.addQuads.push(quad)
 
      else
 
        cb()
 
  parseDels = (cb) =>
 
    parser = N3.Parser()
 
    parser.parse input.patch.deletes, (error, quad, prefixes) =>
 
                  if (quad)
 
                    patch.delQuads.push(quad)
 
                  else
 
                    cb()
 
      if (quad)
 
        patch.delQuads.push(quad)
 
      else
 
        cb()
 

	
 
  async.parallel([parseAdds, parseDels], ((err) => cb(patch)))
 

	
 
class window.RdfDbClient
 
  # Send and receive patches from rdfdb
 
  constructor: (@patchSenderUrl, @clearGraphOnNewConnection, @applyPatch, @setStatus) ->
 
  constructor: (@patchSenderUrl, @clearGraphOnNewConnection, @applyPatch,
 
                @setStatus) ->
 
    @_patchesToSend = []
 
    @_lastPingMs = -1
 
    @_patchesReceived = 0
 
    @_patchesSent = 0
 

	
 
    @_reconnectionTimeout = null
 
@@ -77,13 +78,13 @@ class window.RdfDbClient
 
      #{ping}ms")
 
 
 
  sendPatch: (patch) ->
 
    console.log('rdfdbclient: queue patch to server ', patchSizeSummary(patch))
 
    @_patchesToSend.push(patch)
 
    @_updateStatus()
 
    @_continueSending()           
 
    @_continueSending()
 

	
 
  _newConnection: ->
 
    wsOrWss = window.location.protocol.replace('http', 'ws')
 
    fullUrl = wsOrWss + '//' + window.location.host + @patchSenderUrl
 
    @ws.close() if @ws?
 
    @ws = new WebSocket(fullUrl)
 
@@ -130,18 +131,18 @@ class window.RdfDbClient
 
      return
 

	
 
    # we could call this less often and coalesce patches together to optimize
 
    # the dragging cases.
 

	
 
    sendOne = (patch, cb) =>
 
        toJsonPatch(patch, (json) =>
 
          log('rdfdbclient: send patch to server, ' + json.length + ' bytes')
 
          @ws.send(json)
 
          @_patchesSent++
 
          @_updateStatus()
 
          cb(null)
 
      toJsonPatch(patch, (json) =>
 
        log('rdfdbclient: send patch to server, ' + json.length + ' bytes')
 
        @ws.send(json)
 
        @_patchesSent++
 
        @_updateStatus()
 
        cb(null)
 
      )
 

	
 
    async.eachSeries(@_patchesToSend, sendOne, () =>
 
        @_patchesToSend = []
 
        @_updateStatus()
 
      )
 
      @_patchesToSend = []
 
      @_updateStatus()
 
    )
light9/web/timeline/adjustable.coffee
Show inline comments
 
@@ -15,44 +15,44 @@ class Adjustable
 

	
 
  ctor2: () ->
 
    # config has:
 
    #   getTarget -> vec2 of current target position
 
    #   getSuggestedTargetOffset -> vec2 pixel offset from target
 
    #   emptyBox -> true if you want no value display
 
    
 

	
 
    # updated later by layout algoritm
 
    @centerOffset = $V([0, 0])
 

	
 
  getDisplayValue: () ->
 
    return '' if @config.emptyBox
 
    defaultFormat = d3.format(".4g")(@_getValue())
 
    if @config.getDisplayValue?
 
      return @config.getDisplayValue(@_getValue(), defaultFormat) 
 
      return @config.getDisplayValue(@_getValue(), defaultFormat)
 
    defaultFormat
 

	
 
  getSuggestedCenter: () ->
 
    @getTarget().add(@config.getSuggestedTargetOffset())
 

	
 
  getCenter: () -> # vec2 of pixels
 
    @getTarget().add(@centerOffset)
 

	
 
  getTarget: () -> # vec2 of pixels
 
    @config.getTarget()
 
            
 

	
 
  subscribe: (onChange) ->
 
    # change could be displayValue or center or target. This likely
 
    # calls onChange right away if there's any data yet.
 
    throw new Error('not implemented')
 

	
 
  startDrag: () ->
 
    @initialTarget = @getTarget()
 

	
 
  continueDrag: (pos) ->
 
    ## pos is vec2 of pixels relative to the drag start
 
    @targetDraggedTo = pos.add(@initialTarget)
 
    
 

	
 
  endDrag: () ->
 
    # override
 

	
 
  _editorCoordinates: () -> # vec2 of mouse relative to <l9-t-editor>
 
    return @targetDraggedTo
 
    ev = d3.event.sourceEvent
 
@@ -61,32 +61,32 @@ class Adjustable
 
      rootElem = ev.target
 
    else
 
      rootElem = ev.target.closest('light9-timeline-editor')
 

	
 
    if ev.touches?.length
 
      ev = ev.touches[0]
 
      
 

	
 
    # storing root on the object to remember it across calls in case
 
    # you drag outside the editor.
 
    @root = rootElem.getBoundingClientRect() if rootElem
 
    offsetParentPos = $V([ev.pageX - @root.left, ev.pageY - @root.top])
 

	
 
    return offsetParentPos 
 
    return offsetParentPos
 

	
 
class window.AdjustableFloatObservable extends Adjustable
 
  constructor: (@config) ->
 
    # config also has:
 
    #   observable -> ko.observable we will read and write
 
    #   getValueForPos(pos) -> what should we set to if the user
 
    #                          moves target to this coord?
 
    super()
 
    @ctor2()
 

	
 
  _getValue: () ->
 
    @config.observable()
 
    
 

	
 
  continueDrag: (pos) ->
 
    # pos is vec2 of pixels relative to the drag start.
 
    super(pos)
 
    epos = @_editorCoordinates()
 
    newValue = @config.getValueForPos(epos)
 
    @config.observable(newValue)
 
@@ -107,40 +107,41 @@ class window.AdjustableFloatObject exten
 
    #   getTargetPosForValue(value) -> getTarget result for value
 
    #   getValueForPos
 
    super()
 
    @ctor2()
 
    if not @config.ctx?
 
      throw new Error("missing ctx")
 
    @config.graph.runHandler(@_syncValue.bind(@), "adj sync #{@config.subj.value}")
 
    @config.graph.runHandler(@_syncValue.bind(@),
 
                             "adj sync #{@config.subj.value}")
 

	
 
  _syncValue: () ->
 
    @_currentValue = @config.graph.floatValue(@config.subj, @config.pred)
 
    @_onChange() if @_onChange
 
    
 

	
 
  _getValue: () ->
 
    # this is a big speedup- callers use _getValue about 4x as much as
 
    # the graph changes and graph.floatValue is slow
 
    @_currentValue
 

	
 
  getTarget: () ->
 
    @config.getTargetPosForValue(@_getValue())
 
    
 

	
 
  subscribe: (onChange) ->
 
    # only works on one subscription at a time
 
    throw new Error('multi subscribe not implemented') if @_onChange
 
    @_onChange = onChange
 

	
 
  continueDrag: (pos) ->
 
    # pos is vec2 of pixels relative to the drag start
 
    super(pos)
 
    newValue = @config.getValueForPos(@_editorCoordinates())
 
    
 

	
 
    @config.graph.patchObject(@config.subj, @config.pred,
 
                              @config.graph.LiteralRoundedFloat(newValue),
 
                              @config.ctx)
 
                              
 

	
 
class window.AdjustableFade extends Adjustable
 
  constructor: (@yForV, @i0, @i1, @note, offset, ctx) ->
 
    super()
 
    @config = {
 
      getSuggestedTargetOffset: -> offset
 
      getTarget: @getTarget.bind(@)
 
@@ -153,17 +154,17 @@ class window.AdjustableFade extends Adju
 
    $V([@note.zoomInX(mid.e(1)), @yForV(mid.e(2))])
 

	
 
  _getValue: ->
 
    mid = @note.worldPts[@i0].x(.5).add(@note.worldPts[@i1].x(.5))
 
    mid.e(1)
 

	
 
   continueDrag: (pos) ->
 
  continueDrag: (pos) ->
 
    # pos is vec2 of pixels relative to the drag start
 
    super(pos)
 
    graph = @note.graph
 
    U = (x) => graph.Uri(x)
 
    U = (x) -> graph.Uri(x)
 

	
 
    goalCenterSec = @note.zoomInX.invert(@initialTarget.e(1) + pos.e(1))
 

	
 
    diamSec = @note.worldPts[@i1].e(1) - @note.worldPts[@i0].e(1)
 
    newSec0 = goalCenterSec - diamSec / 2
 
    newSec1 = goalCenterSec + diamSec / 2
light9/web/timeline/adjusters.coffee
Show inline comments
 
@@ -37,13 +37,14 @@ coffeeElementSetup(class AdjustersCanvas
 
        adj.startDrag()
 

	
 
  onMove: (ev) ->
 
    pos = $V([ev.x, ev.y])
 
    if @currentDrag
 
      @currentDrag.cur = pos
 
      @currentDrag.adj.continueDrag(@currentDrag.cur.subtract(@currentDrag.start))
 
      @currentDrag.adj.continueDrag(
 
        @currentDrag.cur.subtract(@currentDrag.start))
 

	
 
  onUp: (ev) ->
 
    return unless @currentDrag
 
    @currentDrag.adj.endDrag()
 
    @currentDrag = null
 
    
 
@@ -156,11 +157,11 @@ coffeeElementSetup(class AdjustersCanvas
 

	
 
    @ctx.font = "12px sans"
 
    @ctx.fillStyle = '#000'
 
    @ctx.fillText(label, x1 + 5, y2 - 5, x2 - x1 - 10)
 

	
 
    # coords from a center that's passed in
 
    # # special layout for the thaeter ones with middinh 
 
    # # special layout for the thaeter ones with middinh
 
    # l/r arrows
 
    # mouse arrow cursor upon hover, and accent the hovered adjuster
 
    # connector
 
)
 
\ No newline at end of file
light9/web/timeline/drawing.coffee
Show inline comments
 
@@ -16,20 +16,20 @@ window.Drawing.svgPathFromPoints = (pts)
 
window.Drawing.line = (ctx, p1, p2) ->
 
  ctx.moveTo(p1.e(1), p1.e(2))
 
  ctx.lineTo(p2.e(1), p2.e(2))
 

	
 
# http://stackoverflow.com/a/4959890
 
window.Drawing.roundRect = (ctx, sx,sy,ex,ey,r) ->
 
    d2r = Math.PI/180
 
    r = ( ( ex - sx ) / 2 ) if ( ex - sx ) - ( 2 * r ) < 0 # ensure that the radius isn't too large for x
 
    r = ( ( ey - sy ) / 2 ) if ( ey - sy ) - ( 2 * r ) < 0 # ensure that the radius isn't too large for y
 
    ctx.beginPath();
 
    ctx.moveTo(sx+r,sy);
 
    ctx.lineTo(ex-r,sy);
 
    ctx.arc(ex-r,sy+r,r,d2r*270,d2r*360,false);
 
    ctx.lineTo(ex,ey-r);
 
    ctx.arc(ex-r,ey-r,r,d2r*0,d2r*90,false);
 
    ctx.lineTo(sx+r,ey);
 
    ctx.arc(sx+r,ey-r,r,d2r*90,d2r*180,false);
 
    ctx.lineTo(sx,sy+r);
 
    ctx.arc(sx+r,sy+r,r,d2r*180,d2r*270,false);
 
    ctx.closePath();
 
  d2r = Math.PI/180
 
  r = ( ( ex - sx ) / 2 ) if ( ex - sx ) - ( 2 * r ) < 0 # ensure that the radius isn't too large for x
 
  r = ( ( ey - sy ) / 2 ) if ( ey - sy ) - ( 2 * r ) < 0 # ensure that the radius isn't too large for y
 
  ctx.beginPath()
 
  ctx.moveTo(sx+r,sy)
 
  ctx.lineTo(ex-r,sy)
 
  ctx.arc(ex-r,sy+r,r,d2r*270,d2r*360,false)
 
  ctx.lineTo(ex,ey-r)
 
  ctx.arc(ex-r,ey-r,r,d2r*0,d2r*90,false)
 
  ctx.lineTo(sx+r,ey)
 
  ctx.arc(sx+r,ey-r,r,d2r*90,d2r*180,false)
 
  ctx.lineTo(sx,sy+r)
 
  ctx.arc(sx+r,sy+r,r,d2r*180,d2r*270,false)
 
  ctx.closePath()
light9/web/timeline/timeline.coffee
Show inline comments
 
@@ -6,24 +6,24 @@ class Project
 
  constructor: (@graph) ->
 

	
 
  makeEffect: (uri) ->
 
    U = (x) => @graph.Uri(x)
 
    effect = U(uri.value + '/effect')
 
    quad = (s, p, o) => @graph.Quad(s, p, o, effect)
 
    
 

	
 
    quads = [
 
      quad(effect, U('rdf:type'), U(':Effect')),
 
      quad(effect, U(':copiedFrom'), uri),
 
      quad(effect, U('rdfs:label'), @graph.Literal(uri.replace(/.*capture\//, ''))),
 
      quad(effect, U(':publishAttr'), U(':strength')),
 
      ]
 

	
 
    fromSettings = @graph.objects(uri, U(':setting'))
 

	
 
    toSettings = @graph.nextNumberedResources(effect + '_set', fromSettings.length)
 
      
 

	
 
    for fs in fromSettings
 
      ts = toSettings.pop()
 
      # full copies of these since I may have to delete captures
 
      quads.push(quad(effect, U(':setting'), ts))
 
      quads.push(quad(ts, U(':device'), @graph.uriValue(fs, U(':device'))))
 
      quads.push(quad(ts, U(':deviceAttr'), @graph.uriValue(fs, U(':deviceAttr'))))
 
@@ -35,42 +35,42 @@ class Project
 
    @graph.applyAndSendPatch({delQuads: [], addQuads: quads})
 
    return effect
 

	
 
  makeNewNote: (song, effect, dropTime, desiredWidthT) ->
 
    U = (x) => @graph.Uri(x)
 
    quad = (s, p, o) => @graph.Quad(s, p, o, song)
 
      
 

	
 
    newNote = @graph.nextNumberedResource("#{song.value}/n")
 
    newCurve = @graph.nextNumberedResource("#{newNote.value}c")
 
    points = @graph.nextNumberedResources("#{newCurve.value}p", 4)
 

	
 
    curveQuads = [
 
        quad(song, U(':note'), newNote)
 
        quad(newNote, U('rdf:type'), U(':Note'))
 
        quad(newNote, U(':originTime'), @graph.LiteralRoundedFloat(dropTime))
 
        quad(newNote, U(':effectClass'), effect)
 
        quad(newNote, U(':curve'), newCurve)
 
        quad(newCurve, U('rdf:type'), U(':Curve'))
 
        quad(newCurve, U(':attr'), U(':strength'))
 
      ]        
 
      ]
 
    pointQuads = []
 

	
 
   
 
    
 

	
 

	
 
    for i in [0...4]
 
      pt = points[i]
 
      pointQuads.push(quad(newCurve, U(':point'), pt))
 
      pointQuads.push(quad(pt, U(':time'), @graph.LiteralRoundedFloat(i/3 * desiredWidthT)))
 
      pointQuads.push(quad(pt, U(':value'), @graph.LiteralRoundedFloat(i == 1 or i == 2)))
 

	
 
    patch = {
 
      delQuads: []
 
      addQuads: curveQuads.concat(pointQuads)
 
      }
 
    @graph.applyAndSendPatch(patch)
 
    
 

	
 
  getCurvePoints: (curve, xOffset) ->
 
    worldPts = []
 
    uris = @graph.objects(curve, @graph.Uri(':point'))
 
    for pt in uris
 
      tm = @graph.floatValue(pt, @graph.Uri(':time'))
 
      val = @graph.floatValue(pt, @graph.Uri(':value'))
 
@@ -81,20 +81,20 @@ class Project
 
    return [uris, worldPts]
 

	
 
  curveWidth: (worldPts) ->
 
    tMin = @graph.floatValue(worldPts[0].uri, @graph.Uri(':time'))
 
    tMax = @graph.floatValue(worldPts[3].uri, @graph.Uri(':time'))
 
    tMax - tMin
 
      
 

	
 
  deleteNote: (song, note, selection) ->
 
    patch = {delQuads: [@graph.Quad(song, graph.Uri(':note'), note, song)], addQuads: []}
 
    @graph.applyAndSendPatch(patch)
 
    if note in selection.selected()
 
      selection.selected(_.without(selection.selected(), note))
 

	
 
    
 

	
 
coffeeElementSetup(class TimelineEditor extends Polymer.mixinBehaviors([Polymer.IronResizableBehavior], Polymer.Element)
 
  @is: 'light9-timeline-editor'
 
  @getter_properties:
 
    viewState: { type: Object }
 
    debug: {type: String}
 
    graph: {type: Object, notify: true}
 
@@ -116,26 +116,26 @@ coffeeElementSetup(class TimelineEditor 
 
    '_onSetAdjuster(setAdjuster)',
 
  ]
 
  constructor: ->
 
    super()
 
    @viewState = new ViewState()
 
    window.viewState = @viewState
 
    
 

	
 
  ready: ->
 
    super.ready()
 
    @addEventListener 'mousedown', (ev) => @$.adjustersCanvas.onDown(ev)
 
    @addEventListener 'mousemove', (ev) => @$.adjustersCanvas.onMove(ev)
 
    @addEventListener 'mouseup', (ev) => @$.adjustersCanvas.onUp(ev)
 

	
 
    ko.options.deferUpdates = true
 
    
 

	
 
    @selection = {hover: ko.observable(null), selected: ko.observable([])}
 

	
 
    window.debug_zoomOrLayoutChangedCount = 0
 
    window.debug_adjUpdateDisplay = 0
 
    
 

	
 
    ko.computed(@zoomOrLayoutChanged.bind(@))
 

	
 
    @trackMouse()
 
    @bindKeys()
 
    @bindWheelZoom(@)
 

	
 
@@ -143,40 +143,40 @@ coffeeElementSetup(class TimelineEditor 
 

	
 
    @addEventListener('iron-resize', @_onIronResize.bind(@))
 
    Polymer.RenderStatus.afterNextRender(this, @_onIronResize.bind(@))
 

	
 
    Polymer.RenderStatus.afterNextRender this, =>
 
      setupDrop(@$.zoomed.$.rows, @$.zoomed.$.rows, @, @$.zoomed.onDrop.bind(@$.zoomed))
 
            
 

	
 
  _onIronResize: ->
 
    @viewState.setWidth(@offsetWidth)
 
    @viewState.coveredByDiagramTop(@$.coveredByDiagram.offsetTop)
 
    @viewState.rowsY(@$.zoomed.$.rows.offsetTop) if @$.zoomed?.$?.rows?
 
    @viewState.audioY(@$.audio.offsetTop)
 
    @viewState.audioH(@$.audio.offsetHeight)
 
    if @$.zoomed?.$?.time?
 
      @viewState.zoomedTimeY(@$.zoomed.$.time.offsetTop)
 
      @viewState.zoomedTimeH(@$.zoomed.$.time.offsetHeight)
 
    
 

	
 
  _onSongTime: (t) ->
 
    @viewState.cursor.t(t)
 
    
 

	
 
  _onSongDuration: (d) ->
 
    d = 700 if d < 1 # bug is that asco isn't giving duration, but 0 makes the scale corrupt
 
    @viewState.zoomSpec.duration(d)
 
    
 

	
 
  _onSong: (s) ->
 
    @song = @playerSong if @followPlayerSong
 
    
 

	
 
  _onGraph: (graph) ->
 
    @project = new Project(graph)
 
    @show = 'http://light9.bigasterisk.com/show/dance2017'
 

	
 
  _onSetAdjuster: () ->
 
    @makeZoomAdjs()
 
    
 

	
 
  updateDebugSummary: ->
 
    elemCount = (tag) -> document.getElementsByTagName(tag).length
 
    @debug = "#{window.debug_zoomOrLayoutChangedCount} layout change,
 
     #{elemCount('light9-timeline-note')} notes,
 
     #{@selection.selected().length} selected
 
     #{elemCount('light9-timeline-graph-row')} rows,
 
@@ -187,13 +187,13 @@ coffeeElementSetup(class TimelineEditor 
 
  zoomOrLayoutChanged: ->
 
    vs = @viewState
 
    dependOn = [vs.zoomSpec.t1(), vs.zoomSpec.t2(), vs.width()]
 

	
 
    # shouldn't need this- deps should get it
 
    @$.zoomed.gatherNotes() if @$.zoomed?.gatherNotes?
 
  
 

	
 
    # todo: these run a lot of work purely for a time change
 
    if @$.zoomed?.$?.audio?
 
      #@dia.setTimeAxis(vs.width(), @$.zoomed.$.audio.offsetTop, vs.zoomInX)
 
      @$.adjustersCanvas.updateAllCoords()
 

	
 
  trackMouse: ->
 
@@ -234,16 +234,16 @@ coffeeElementSetup(class TimelineEditor 
 
    shortcut.add 'Delete', =>
 
      for note in @selection.selected()
 
        @project.deleteNote(@graph.Uri(@song), note, @selection)
 

	
 
  makeZoomAdjs: ->
 
    yMid = => @$.audio.offsetTop + @$.audio.offsetHeight / 2
 
    
 

	
 
    valForPos = (pos) =>
 
        x = pos.e(1)
 
        t = @viewState.fullZoomX.invert(x)
 
      x = pos.e(1)
 
      t = @viewState.fullZoomX.invert(x)
 
    @setAdjuster('zoom-left', => new AdjustableFloatObservable({
 
      observable: @viewState.zoomSpec.t1,
 
      getTarget: () =>
 
        $V([@viewState.fullZoomX(@viewState.zoomSpec.t1()), yMid()])
 
      getSuggestedTargetOffset: () => $V([50, 0])
 
      getValueForPos: valForPos
 
@@ -255,30 +255,30 @@ coffeeElementSetup(class TimelineEditor 
 
        $V([@viewState.fullZoomX(@viewState.zoomSpec.t2()), yMid()])
 
      getSuggestedTargetOffset: () => $V([-50, 0])
 
      getValueForPos: valForPos
 
    }))
 

	
 
    panObs = ko.pureComputed({
 
        read: () =>
 
          (@viewState.zoomSpec.t1() + @viewState.zoomSpec.t2()) / 2
 
        write: (value) =>
 
          zs = @viewState.zoomSpec
 
          span = zs.t2() - zs.t1()
 
          zs.t1(value - span / 2)
 
          zs.t2(value + span / 2)
 
      })
 
      read: () =>
 
        (@viewState.zoomSpec.t1() + @viewState.zoomSpec.t2()) / 2
 
      write: (value) =>
 
        zs = @viewState.zoomSpec
 
        span = zs.t2() - zs.t1()
 
        zs.t1(value - span / 2)
 
        zs.t2(value + span / 2)
 
    })
 

	
 
    @setAdjuster('zoom-pan', => new AdjustableFloatObservable({
 
      observable: panObs
 
      emptyBox: true
 
      # fullzoom is not right- the sides shouldn't be able to go
 
      # offscreen
 
      getTarget: () => $V([@viewState.fullZoomX(panObs()), yMid()])
 
      getSuggestedTargetOffset: () => $V([0, 0])
 
      getValueForPos: valForPos
 
      }))
 
    }))
 
)
 

	
 

	
 
# plan: in here, turn all the notes into simple js objects with all
 
# their timing data and whatever's needed for adjusters. From that, do
 
# the brick layout. update only changing adjusters.
 
@@ -297,42 +297,42 @@ coffeeElementSetup(class TimeZoomed exte
 
  ]
 
  constructor: ->
 
    super()
 
    @notes = []
 
    @stage = new PIXI.Container()
 
    @stage.interactive=true
 
    
 

	
 
    @renderer = PIXI.autoDetectRenderer({
 
        backgroundColor: 0x606060,
 
        antialias: true,
 
        forceCanvas: true,
 
      backgroundColor: 0x606060,
 
      antialias: true,
 
      forceCanvas: true,
 
    })
 
     
 

	
 
  ready: ->
 
    super.ready()
 

	
 
    @addEventListener('iron-resize', @_onResize.bind(@))
 
    Polymer.RenderStatus.afterNextRender(this, @_onResize.bind(@))
 
    
 

	
 
    @$.rows.appendChild(@renderer.view)
 

	
 
    # This works for display, but pixi hit events didn't correctly
 
    # move with the objects, so as a workaround, I extended the top of
 
    # the canvas in _onResize.
 
    # 
 
    #
 
    #ko.computed =>
 
    #  @stage.setTransform(0, -(@viewState.rowsY()), 1, 1, 0, 0, 0, 0, 0)
 
      
 

	
 
  _onResize: ->
 
    @$.rows.firstChild.style.position = 'relative'
 
    @$.rows.firstChild.style.top = -@viewState.rowsY() + 'px'
 

	
 
    @renderer.resize(@clientWidth, @clientHeight + @viewState.rowsY())
 
    
 

	
 
    @renderer.render(@stage)
 
  
 

	
 
  _onGraph: (graph, setAdjuster, song, viewState, project)->
 
    return unless @song # polymer will call again
 
    @graph.runHandler(@gatherNotes.bind(@), 'zoom notes')
 
  onZoom: ->
 
    updateZoomFlattened = ->
 
      log('updateZoomFlattened')
 
@@ -341,31 +341,31 @@ coffeeElementSetup(class TimeZoomed exte
 

	
 
  gatherNotes: ->
 
    U = (x) => @graph.Uri(x)
 
    return unless @song?
 

	
 
    songNotes = @graph.objects(U(@song), U(':note'))
 
    
 

	
 
    @stage.removeChildren()
 
    n.destroy() for n in @notes
 
    @notes = []
 
    
 

	
 
    noteNum = 0
 
    for uri in _.sortBy(songNotes, 'id')
 
      con = new PIXI.Container()
 
      con.interactive=true
 
      @stage.addChild(con)
 
      
 

	
 
      row = noteNum % 6
 
      rowTop = @viewState.rowsY() + 20 + 150 * row
 
      note = new Note(@, con, @project, @graph, @selection, uri, @setAdjuster, U(@song), @viewState, rowTop, rowTop + 140)
 
      @notes.push(note)
 
      noteNum = noteNum + 1
 
 
 

	
 
    @renderer.render(@stage)
 
    
 

	
 
  onDrop: (effect, pos) ->
 
    U = (x) => @graph.Uri(x)
 

	
 
    return unless effect and effect.match(/^http/)
 

	
 
    # we could probably accept some initial overrides right on the
 
@@ -444,29 +444,29 @@ class Note
 
    throw new Error("curve #{@uri.value} has no attr #{curveAttr.value}")
 

	
 
  draw: ->
 
    U = (x) => @graph.Uri(x)
 
    [pointUris, worldPts] = @getCurvePoints(@uri, U(':strength'))
 
    effect = @graph.uriValue(@uri, U(':effectClass'))
 
    
 

	
 
    yForV = (v) => @rowBotY + (@rowTopY - @rowBotY) * v
 
    dependOn = [@viewState.zoomSpec.t1(), @viewState.zoomSpec.t2(), @viewState.width()]
 
    screenPts = (new PIXI.Point(@viewState.zoomInX(pt.e(1)), yForV(pt.e(2))) for pt in worldPts)
 

	
 
    @container.removeChildren()    
 
    @container.removeChildren()
 
    graphics = new PIXI.Graphics({nativeLines: false})
 
    graphics.interactive = true
 
    @container.addChild(graphics)
 

	
 
    shape = new PIXI.Polygon(screenPts)
 
    graphics.beginFill(@_noteColor(effect), .313)
 
    graphics.drawShape(shape)
 
    graphics.endFill()
 

	
 
    # stroke should vary with @selection.hover() == @uri and with @uri in @selection.selected()
 
    # 
 
    #
 
    # #notes > path.hover {stroke-width: 1.5; stroke: #888;}
 
    # #notes > path.selected {stroke-width: 5; stroke: red;}
 
    graphics.lineStyle(2, 0xffd900, 1)
 
    graphics.moveTo(screenPts[0].x, screenPts[0].y)
 
    for p in screenPts.slice(1)
 
      graphics.lineTo(p.x, p.y)
 
@@ -484,13 +484,13 @@ class Note
 
      @selection.hover(null)
 

	
 
    @graphics = graphics
 
    curveWidthCalc = () => @project.curveWidth(worldPts)
 
    @_updateAdjusters(screenPts, worldPts, curveWidthCalc, yForV, @song)
 
    @_updateInlineAttrs(screenPts)
 
    
 

	
 
  onUri: ->
 
    @graph.runHandler(@update.bind(@), "note updates #{@uri}")
 

	
 
  patchCouldAffectMe: (patch) ->
 
    if patch and patch.addQuads # sometimes patch is a polymer-sent value. @update is used as a listener too
 
      if patch.addQuads.length == patch.delQuads.length == 1
 
@@ -498,13 +498,13 @@ class Note
 
        del = patch.delQuads[0]
 
        if (add.predicate.equals(del.predicate) and del.predicate.equals(@graph.Uri(':time')) and add.subject.equals(del.subject))
 
          timeEditFor = add.subject
 
          if @worldPts and timeEditFor not in @pointUris
 
            return false
 
    return true
 
            
 

	
 
  update: (patch) ->
 
    # update our note DOM and SVG elements based on the graph
 
    if not @patchCouldAffectMe(patch)
 
      # as autodep still fires all handlers on all patches, we just
 
      # need any single dep to cause another callback. (without this,
 
      # we would no longer be registered at all)
 
@@ -522,13 +522,13 @@ class Note
 
      @_makeOffsetAdjuster(yForV, curveWidthCalc, ctx)
 
      @_makeCurvePointAdjusters(yForV, worldPts, ctx)
 
      @_makeFadeAdjusters(yForV, ctx, worldPts)
 

	
 
  _updateInlineAttrs: (screenPts) ->
 
    w = 280
 
    
 

	
 
    leftX = Math.max(2, screenPts[Math.min(1, screenPts.length - 1)].x + 5)
 
    rightX = screenPts[Math.min(2, screenPts.length - 1)].x - 5
 
    if screenPts.length < 3
 
      rightX = leftX + w
 

	
 
    if rightX - leftX < w or rightX < w or leftX > @parentElem.offsetWidth
 
@@ -541,13 +541,13 @@ class Note
 
      top: @rowTopY + 5,
 
      width: w,
 
      height: @rowBotY - @rowTopY - 15,
 
      }
 

	
 
    @parentElem.updateInlineAttrs(@uri, config)
 
    
 

	
 
  _makeCurvePointAdjusters: (yForV, worldPts, ctx) ->
 
    for pointNum in [0...worldPts.length]
 
      @_makePointAdjuster(yForV, worldPts, pointNum, ctx)
 

	
 
  _makePointAdjuster: (yForV, worldPts, pointNum, ctx) ->
 
    U = (x) => @graph.Uri(x)
 
@@ -576,13 +576,13 @@ class Note
 

	
 
  _makeOffsetAdjuster: (yForV, curveWidthCalc, ctx) ->
 
    U = (x) => @graph.Uri(x)
 

	
 
    adjId = @uri.value + '/offset'
 
    @adjusterIds[adjId] = true
 
    @setAdjuster adjId, => 
 
    @setAdjuster adjId, =>
 
      adj = new AdjustableFloatObject({
 
        graph: @graph
 
        subj: @uri
 
        pred: U(':originTime')
 
        ctx: ctx
 
        getDisplayValue: (v, dv) => "o=#{dv}"
 
@@ -602,19 +602,19 @@ class Note
 
    @_makeFadeAdjuster(yForV, ctx, @uri.value + '/fadeOut', n - 2, n - 1, $V([50, -10]))
 

	
 
  _makeFadeAdjuster: (yForV, ctx, adjId, i0, i1, offset) ->
 
    return # not ready- AdjustableFade looks in Note object
 
    @adjusterIds[adjId] = true
 
    @setAdjuster adjId, => new AdjustableFade(yForV, i0, i1, @, offset, ctx)
 
    
 

	
 
  _suggestedOffset: (pt) ->
 
    if pt.e(2) > .5
 
      $V([0, 30])
 
    else
 
      $V([0, -30])
 
  
 

	
 
  _onMouseDown: (ev) ->
 
    sel = @selection.selected()
 
    if ev.data.originalEvent.ctrlKey
 
      if @uri in sel
 
        sel = _.without(sel, @uri)
 
      else
 
@@ -623,22 +623,22 @@ class Note
 
      sel = [@uri]
 
    @selection.selected(sel)
 

	
 
  _noteColor: (effect) ->
 
    effect = effect.value
 
    if effect in ['http://light9.bigasterisk.com/effect/blacklight',
 
      'http://light9.bigasterisk.com/effect/strobewarm']
 
                  'http://light9.bigasterisk.com/effect/strobewarm']
 
      hue = 0
 
      sat = 100
 
    else        
 
    else
 
      hash = 0
 
      for i in [(effect.length-10)...effect.length]
 
        hash += effect.charCodeAt(i)
 
      hue = (hash * 8) % 360
 
      sat = 40 + (hash % 20) # don't conceal colorscale too much
 

	
 
    return parseInt(tinycolor.fromRatio({h: hue / 360, s: sat / 100, l: .58}).toHex(), 16)
 

	
 
    #elem = @getOrCreateElem(uri+'/label', 'noteLabels', 'text', {style: "font-size:13px;line-height:125%;font-family:'Verana Sans';text-align:start;text-anchor:start;fill:#000000;"})
 
    #elem.setAttribute('x', curvePts[0].e(1)+20)
 
    #elem.setAttribute('y', curvePts[0].e(2)-10)
 
    #elem.innerHTML = effectLabel;
 
    #elem.innerHTML = effectLabel
light9/web/timeline/viewstate.coffee
Show inline comments
 
@@ -20,13 +20,13 @@ class window.ViewState
 
      
 
    @fullZoomX = d3.scaleLinear()
 
    @zoomInX = d3.scaleLinear()
 

	
 
    @zoomAnimSec = .1
 

	
 
    ko.computed(@maintainZoomLimitsAndScales.bind(@))    
 
    ko.computed(@maintainZoomLimitsAndScales.bind(@))
 
 
 
  setWidth: (w) ->
 
    @width(w)
 
    @maintainZoomLimitsAndScales() # before other handlers run
 
    
 
  maintainZoomLimitsAndScales: () ->
 
@@ -84,9 +84,9 @@ class window.ViewState
 
          @zoomSpec.t1((1 - frac) * oldT1 + frac * newT1)
 
          @zoomSpec.t2((1 - frac) * oldT2 + frac * newT2)
 
        delay = frac * secs * 1000
 
        setTimeout(gotoStep, delay)
 
        lastTime = delay
 
    setTimeout(=>
 
        @zoomSpec.t1(newT1)
 
        @zoomSpec.t2(newT2)
 
      , lastTime + 10)  
 
      @zoomSpec.t1(newT1)
 
      @zoomSpec.t2(newT2)
 
    , lastTime + 10)
package.json
Show inline comments
 
@@ -11,12 +11,13 @@
 
  "dependencies": {
 
    "@webcomponents/shadycss": "^1.1.3",
 
    "@webcomponents/webcomponentsjs": "^1.2.0",
 
    "bower": "^1.8.4",
 
    "browserify": "^16.2.0",
 
    "chai": "^3.5.0",
 
    "coffeelint": "^2.1.0",
 
    "coffeescript": "^2.3.0",
 
    "d3": "^5.1.0",
 
    "mocha": "^2.5.3",
 
    "n3": "^1.0.0-alpha",
 
    "pixi.js": "^4.7.3",
 
    "tinycolor2": "^1.4.1"
0 comments (0 inline, 0 general)