wip: pdu encoder

wip: pdu encoder

--- src/pdu.coffee
+++ src/pdu.coffee
@@ -6,6 +6,12 @@
 vrs = require("../lib/vrs")

 log = require("./logger")('pdu')
+
+# helper: total length for array of buffers
+total_length = (arr) ->
+  arr.reduce((sum, buff) ->
+    return sum + buff.length
+  , 0)

 ##
 # PDUDecoder
@@ -166,11 +172,12 @@
     for item in @presentation_context
       _buffers.push item.encode()
     # _buffers.push @user_information.encode()
-    _var_len = _buffers.reduce (b1, b2) ->
-      return b1.length + b2.length
+    _var_len = total_length(_buffers)
     _header = Buffer.concat([new Buffer([0x01, 0x00]), mk_uint32(66 + _var_len),
                               # protocol version
                               mk_uint16(1),
+                              # reserved
+                              new Buffer([0x00, 0x00]),
                               # called & calling aet title
                               new Buffer(printf("%-16s%-16s", @called_aet_title.substr(0,16),
                                 @calling_aet_title.substr(0,16)), 'binary'),
@@ -230,7 +237,9 @@
       @abstract_syntax.encode()
       Buffer.concat(_ts.encode() for _ts in @transfer_syntax)
     ]
-    _len = _buffers.reduce (b1, b2) -> b1.length + b2.length
+    log.trace(buffers: _buffers, "PresentationContextItem>encode")
+    _len = total_length(_buffers)
+    log.trace(length: _len, "PresentationContextItem>encode")
     _header = Buffer.concat([new Buffer([0x20, 0]), mk_uint16(_len)])
     _buffers[0] = _header
     return Buffer.concat(_buffers)
@@ -438,6 +447,11 @@
   _enc = new PDUEncoder()
   _enc.on 'data', (buff) ->
     console.log "BUFFER:", buff
+    _dec = new PDUDecoder()
+    _dec.on 'data', (pdu) ->
+      console.log "encoded/decoded pdu", pdu.to_json()
+    _dec.write buff
+    _dec.end()
   _enc.write _pdu

 ###


Bug fixes with mousemove event

Bug fixes with mousemove event

--- src/controller.coffee
+++ src/controller.coffee
@@ -786,12 +786,12 @@

       # Translate it immediately into position
       position = new draw.Point(
-        point.x + @draggingOffset.x + getOffsetTop(@iceElement),
-        point.y + @draggingOffset.y + getOffsetLeft(@iceElement)
+        point.x + @draggingOffset.x,
+        point.y + @draggingOffset.y
       )

-      @dragCanvas.style.top = "#{position.y}px"
-      @dragCanvas.style.left = "#{position.x}px"
+      @dragCanvas.style.top = "#{position.y + getOffsetTop(@iceElement)}px"
+      @dragCanvas.style.left = "#{position.x + getOffsetLeft(@iceElement)}px"

       # Now we are done with the "clickedX" suite of stuff.
       @clickedPoint = @clickedBlock = null
@@ -810,8 +810,8 @@
         point.y + @draggingOffset.y + getOffsetTop(@iceElement)
       )

-      @dragCanvas.style.top = "#{position.y}px"
-      @dragCanvas.style.left = "#{position.x}px"
+      @dragCanvas.style.top = "#{position.y + getOffsetTop(@iceElement)}px"
+      @dragCanvas.style.left = "#{position.x + getOffsetLeft(@iceElement)}px"

       mainPoint = @trackerPointToMain(position)


Special case first row with animation

Special case first row with animation

--- src/controller.coffee
+++ src/controller.coffee
@@ -2411,8 +2411,11 @@

       unless setValueResult.success
         return setValueResult
-
-      @mainScroller.scrollTop = @view.getViewNodeFor(@tree).bounds[@aceEditor.getFirstVisibleRow()].y
+
+      if @aceEditor.getFirstVisibleRow() is 0
+        @mainScroller.scrollTop = 0
+      else
+        @mainScroller.scrollTop = @view.getViewNodeFor(@tree).bounds[@aceEditor.getFirstVisibleRow()].y

       setTimeout (=>
         @setFontSize @aceEditor.getFontSize()


dropdown positioning missing px, set minWidth to socket width

--- src/controller.coffee
+++ src/controller.coffee
@@ -2139,8 +2139,9 @@

       location = @view.getViewNodeFor(@textFocus).bounds[0]

-      @dropdownElement.style.top = location.y + @fontSize - @scrollOffsets.main.y
-      @dropdownElement.style.left = location.x - @scrollOffsets.main.x + @dropletElement.offsetLeft + @mainCanvas.offsetLeft
+      @dropdownElement.style.top = location.y + @fontSize - @scrollOffsets.main.y + 'px'
+      @dropdownElement.style.left = location.x - @scrollOffsets.main.x + @dropletElement.offsetLeft + @mainCanvas.offsetLeft + 'px'
+      @dropdownElement.style.minWidth = location.width + 'px'

   Editor::hideDropdown= ->
     @dropdownElement.style.display = 'none'


delay jobs by onetick

delay jobs by onetick

--- src/wrap.coffee
+++ src/wrap.coffee
@@ -77,7 +77,7 @@
     work: (job) ->
         if job?
             @working = yes
-            job.call(this, => @work(@queue.shift()))
+            process.nextTick(job.bind(this, => @work(@queue.shift())))
         else
             @working = no
             @end() if @ending


remove sinon-js require

remove sinon-js require

--- factories.js.coffee
+++ factories.js.coffee
@@ -1,4 +1,3 @@
-#= require sinon-1.4.2

 sequencer = (property) ->
   value = if @sequences[property]?


smaller generated js code

smaller generated js code

--- src/xml.coffee
+++ src/xml.coffee
@@ -60,6 +60,7 @@
                         tag.removeListener event, pipe[event]
                     return
             throw new Error("this shouldn't happen D:")
+        return
     @emit 'add', tag
     return tag


* scroll

* scroll

--- app/assets/javascripts/maker.js.coffee
+++ app/assets/javascripts/maker.js.coffee
@@ -71,18 +71,23 @@
     large_card  = $('#show_in_editor .large-card:first')

     if large_card.length && large_card.microdata('uuid') == node_uuid
-      $('#show_in_editor').hide().html('')
-      $('#new_in_editor').fadeIn(100)
+      this.close()
     else
-      $('#new_in_editor').hide()
-      path = card.microdata('path')
-      $('#show_in_editor').load path, ->
-        $('#show_in_editor').fadeIn(100)
-        $(document).foundation('tab', 'reflow');
-        pfe = new DH.Card.AddPropertyFieldEditor
-        pfe.add_control_fields()
+      this.open(card)

+  close: () ->
+    $('#show_in_editor').hide().html('')
+    $('#new_in_editor').fadeIn(100)

+  open: (card) ->
+    path = card.microdata('path')
+    $('html, body').animate({scrollTop:0}, 'fast');
+    $('#new_in_editor').hide()
+    $('#show_in_editor').load path, ->
+      $('#show_in_editor').fadeIn(100)
+      $(document).foundation('tab', 'reflow');
+      pfe = new DH.Card.AddPropertyFieldEditor
+      pfe.add_control_fields()


If there is only one rol no double popup is required for updating US points

--- app/coffee/modules/backlog/main.coffee
+++ app/coffee/modules/backlog/main.coffee
@@ -495,7 +495,12 @@
         # Watchers
         bindOnce $scope, "project", (project) ->
             roles = _.filter(project.roles, "computable")
-            $el.append(selectionTemplate({ 'roles':  roles }))
+            numberOfRoles = _.size(roles)
+
+            if numberOfRoles > 1
+                $el.append(selectionTemplate({ 'roles':  roles }))
+            else
+                $el.find(".icon-arrow-bottom").remove()

         $scope.$on "uspoints:select", (ctx, roleId, roleName) ->
             $el.find(".popover").hide()
@@ -562,12 +567,17 @@
         us = $scope.$eval($attrs.tgUsPoints)
         updatingSelectedRoleId = null
         selectedRoleId = null
+        numberOfRoles = _.size(us.points)
+
+        # Preselect the rol if we have only one
+        if numberOfRoles == 1
+            selectedRoleId = _.keys(us.points)[0]

         updatePoints = (roleId) ->
             pointsDom = $el.find("a > span.points-value")
             usTotalPoints = calculateTotalPoints(us)
             us.total_points = usTotalPoints
-            if not roleId?
+            if not roleId? or numberOfRoles == 1
                 pointsDom.text(us.total_points)
             else
                 pointId = us.points[roleId]


Add factors to inspect(frame)

Add factors to inspect(frame)

--- src/ext/modules/routines.coffee
+++ src/ext/modules/routines.coffee
@@ -449,90 +449,94 @@
       scores: inspectScores { model: modelKey, frame: frameKey }, [ prediction ]
       metrics: inspectMetrics { model: modelKey, frame: frameKey }, [ prediction ]

+  inspectFrameColumns = (tableLabel, frameKey, frame, frameColumns) -> ->
+    variables = [
+      Flow.Data.Variable 'label', TString
+      Flow.Data.Variable 'missing', TNumber
+      Flow.Data.Variable 'zeros', TNumber
+      Flow.Data.Variable 'pinfs', TNumber
+      Flow.Data.Variable 'ninfs', TNumber
+      Flow.Data.Variable 'min', TNumber
+      Flow.Data.Variable 'max', TNumber
+      Flow.Data.Variable 'mean', TNumber
+      Flow.Data.Variable 'sigma', TNumber
+      Flow.Data.Variable 'type', TString
+      Flow.Data.Variable 'cardinality', TNumber
+      Flow.Data.Variable 'precision', TNumber
+    ]
+
+    Record = Flow.Data.Record variables
+    rows = for column in frameColumns
+      row = new Record()
+      for variable in variables
+        label = variable.label
+        switch label
+          when 'min'
+            row[label] = head column.mins
+          when 'max'
+            row[label] = head column.maxs
+          when 'cardinality'
+            row[label] = if domain = column.domain then domain.length else null
+          else
+            row[label] = column[label]
+      row
+
+    Flow.Data.Table
+      label: tableLabel
+      description: "A list of #{tableLabel} in the H2O Frame."
+      variables: variables
+      rows: rows
+      meta:
+        origin: "getFrame #{stringify frameKey}"
+
+  inspectFrameData = (frameKey, frame) -> ->
+    frameColumns = frame.columns
+    variables = for column in frameColumns
+      #XXX format functions
+      switch column.type
+        when 'int'
+          Flow.Data.Variable column.label, TNumber
+        when 'real'
+          Flow.Data.Variable column.label, TNumber
+        when 'enum'
+          Flow.Data.Factor column.label, column.domain
+        when 'uuid', 'string'
+          Flow.Data.Variable column.label, TString
+        when 'time'
+          Flow.Data.Variable column.label, TDate
+        else
+          Flow.Data.Variable column.label, TObject
+
+    Record = Flow.Data.Record variables
+    rowCount = (head frameColumns).data.length
+    rows = for i in [0 ... rowCount]
+      row = new Record()
+      for variable, j in variables
+        value = frameColumns[j].data[i]
+        switch variable.type
+          when TNumber, TNumber
+            #TODO handle +-Inf
+            row[variable.label] = if value is 'NaN' then null else value
+          else
+            row[variable.label] = value
+      row
+
+    Flow.Data.Table
+      label: 'data'
+      description: 'A partial list of rows in the H2O Frame.'
+      variables: variables
+      rows: rows
+      meta:
+        origin: "getFrame #{stringify frameKey}"
+
   extendFrame = (frameKey, frame) ->
-    inspectColumns = ->
-      variables = [
-        Flow.Data.Variable 'label', TString
-        Flow.Data.Variable 'missing', TNumber
-        Flow.Data.Variable 'zeros', TNumber
-        Flow.Data.Variable 'pinfs', TNumber
-        Flow.Data.Variable 'ninfs', TNumber
-        Flow.Data.Variable 'min', TNumber
-        Flow.Data.Variable 'max', TNumber
-        Flow.Data.Variable 'mean', TNumber
-        Flow.Data.Variable 'sigma', TNumber
-        Flow.Data.Variable 'type', TString
-        Flow.Data.Variable 'cardinality', TNumber
-        Flow.Data.Variable 'precision', TNumber
-      ]
-
-      Record = Flow.Data.Record variables
-      rows = for column in frame.columns
-        row = new Record()
-        for variable in variables
-          label = variable.label
-          switch label
-            when 'min'
-              row[label] = head column.mins
-            when 'max'
-              row[label] = head column.maxs
-            when 'cardinality'
-              row[label] = if domain = column.domain then domain.length else null
-            else
-              row[label] = column[label]
-        row
-
-      Flow.Data.Table
-        label: 'columns'
-        description: 'A list of columns in the H2O Frame.'
-        variables: variables
-        rows: rows
-        meta:
-          origin: "getFrame #{stringify frameKey}"
-
-    inspectData = ->
-      frameColumns = frame.columns
-      variables = for column in frameColumns
-        #XXX format functions
-        switch column.type
-          when 'int'
-            Flow.Data.Variable column.label, TNumber
-          when 'real'
-            Flow.Data.Variable column.label, TNumber
-          when 'enum'
-            Flow.Data.Factor column.label, column.domain
-          when 'uuid', 'string'
-            Flow.Data.Variable column.label, TString
-          when 'time'
-            Flow.Data.Variable column.label, TDate
-          else
-            Flow.Data.Variable column.label, TObject
-
-      Record = Flow.Data.Record variables
-      rowCount = (head frame.columns).data.length
-      rows = for i in [0 ... rowCount]
-        row = new Record()
-        for variable, j in variables
-          value = frameColumns[j].data[i]
-          switch variable.type
-            when TNumber, TNumber
-              #TODO handle +-Inf
-              row[variable.label] = if value is 'NaN' then null else value
-            else
-              row[variable.label] = value
-        row
-
-      Flow.Data.Table
-        label: 'data'
-        description: 'A partial list of rows in the H2O Frame.'
-        variables: variables
-        rows: rows
-        meta:
-          origin: "getFrame #{stringify frameKey}"
-
-    inspect_ frame,
-      columns: inspectColumns
-      data: inspectData
+    inspections =
+      columns: inspectFrameColumns 'columns', frameKey, frame, frame.columns
+      data: inspectFrameData frameKey, frame
+
+    enumColumns = (column for column in frame.columns when column.type is 'enum')
+    inspections.factors = inspectFrameColumns 'factors', frameKey, frame, enumColumns if enumColumns.length > 0
+    inspect_ frame, inspections

   extendColumnSummary = (frameKey, frame, columnName) ->
     column = head frame.columns


Fix inspect() for bad array-valued model parameters

--- src/ext/modules/routines.coffee
+++ src/ext/modules/routines.coffee
@@ -202,7 +202,7 @@
         when 'byte', 'short', 'int', 'long', 'float', 'double'
           Flow.Data.Variable parameter.label, TNumber
         when 'string[]'
-          Flow.Data.Variable parameter.label, TArray
+          Flow.Data.Variable parameter.label, TString
         when 'boolean'
           Flow.Data.Variable parameter.label, TBoolean
         else
@@ -362,6 +362,7 @@
     if algos.length is 1
       inspect_ models,
         parameters: inspectMultimodelParameters models
+

     render_ models, -> H2O.ModelsOutput _, models


check for float texture extension

check for float texture extension

--- app/controllers/quick_dashboard.coffee
+++ app/controllers/quick_dashboard.coffee
@@ -56,11 +56,18 @@
     for name in ['webgl', 'experimental-webgl']
       try
         context = canvas.getContext(name)
+
+        # Check if browser support floating-point textures
+        ext = context.getExtension('OES_texture_float')
+
       catch error
         continue
       break if context?

     lib = if context? then 'gl' else 'canvas'
+
+    # Default to canvas if browser does not support WebGL floating-point texture extension
+    lib = if ext? then 'gl' else 'canvas'

     # Default to canvas if Safari regardless of WebGL
     lib = 'canvas' if userAgent.browser is 'safari'


github-commit-link: Loosen regexp to match 7-through-40-char hashes

Instead of 7-or-40-char hashes (e.g. not 8-character hashes).  The
{m,n} syntax is part of POSIX's basic regular expressions, although
POSIX uses \{m,n\} [1].  It looks like CoffeeScript also supports this
range syntax [2]:

  | \.{2,3}           # range or splat

but I couldn't find a clear regexp specification while skimming the
CoffeeScript docs.

[1]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_03_06
[2]: http://coffeescript.org/#regexes

--- src/scripts/github-commit-link.coffee
+++ src/scripts/github-commit-link.coffee
@@ -28,7 +28,7 @@

 module.exports = (robot) ->
   github = require("githubot")(robot)
-  robot.hear /.*(\b[0-9a-f]{7}\b|\b[0-9a-f]{40}\b).*/i, (msg) ->
+  robot.hear /.*(\b[0-9a-f]{7,40}\b).*/i, (msg) ->
     if process.env.HUBOT_GITHUB_REPO && process.env.HUBOT_GITHUB_TOKEN
       if !(msg.message.text.match(/commit\//))
         commit_sha = msg.match[1].replace /\b/, ""


Re added report parsing

Re added report parsing

--- src/scripts/search-virus-total.coffee
+++ src/scripts/search-virus-total.coffee
@@ -53,13 +53,16 @@

     robot.http(vt_url_report_url)
       .post(data) (err, res, body) ->
-        # vt_json = JSON.parse(body)
-        #
-        # summary = """ VirusTotal URL Result: #{vt_json.resource}
-        # - Scanned at: #{vt_json.scan_date}
-        # - Results:    #{vt_json.positives}/#{vt_json.total}
-        # - Link:       #{vt_json.permalink}
-        # """
+        vt_json = JSON.parse(body)
+
+        if vt_json.response_code == 1
+          summary = """ VirusTotal URL Result: #{vt_json.url}
+          - Scanned at: #{vt_json.scan_date}
+          - Results:    #{vt_json.positives}/#{vt_json.total}
+          - Link:       #{vt_json.permalink}
+          """
+
+          msg.send summary


Send nodeId instead so we can test complex graphs more easily

--- spec/Scoping.coffee
+++ spec/Scoping.coffee
@@ -23,7 +23,7 @@
     forwardGroups: true
   , (data, groups, out, callback) ->
     setTimeout ->
-      out.send data + 'foo'
+      out.send data + c.nodeId
       callback()
     , 1

@@ -37,7 +37,7 @@
   c.process (input, output) ->
     data = input.getData 'in'
     setTimeout ->
-      output.sendDone data + 'bar'
+      output.sendDone data + c.nodeId
     , 1

 describe 'Scope isolation', ->
@@ -81,7 +81,7 @@
         'CONN'
         '< 1'
         '< a'
-        'DATA bazfoobar'
+        'DATA bazWpPc'
         '>'
         '>'
         'DISC'


Stop event propagation from the share component.

Fixes motif/company#2219

--- framer/Components/ShareComponent.coffee
+++ framer/Components/ShareComponent.coffee
@@ -95,9 +95,9 @@
 		truncate = (str, n) ->
 			str.substr(0, n-1).trim() + "…"

-		if @shareInfo.twitter and @shareInfo.title.length > 26
+		if @shareInfo.twitter and @shareInfo.title?.length > 26
 			@shareInfo.title = truncate(@shareInfo.title, 26)
-		else if @shareInfo.title.length > 34
+		else if @shareInfo.title?.length > 34
 			@shareInfo.title = truncate(@shareInfo.title, 34)

 	# Render main sheet
@@ -489,6 +489,11 @@
 			@style =
 				cursor: "default"

+		# Disable events propagating up to block unintented interactions
+		@sheet.onTouchStart (event) -> event.stopPropagation()
+		@sheet.onTouchEnd (event) -> event.stopPropagation()
+		@sheet.onTouchMove (event) -> event.stopPropagation()
+
 		# Toggle sheet when clicked on close or open buttons
 		@close.onClick =>
 			@options.fixed = true


Little cleanup

Little cleanup

--- src/dockerfile.coffee
+++ src/dockerfile.coffee
@@ -21,7 +21,7 @@
 class Dockerfile
   constructor: ->
     @commands = []
-  count: -> return @commands.length
+  count: -> @commands.length
   add: (command) ->
     if command.overrides() and @commands.filter((c) -> functions.sameCommand(c, command)).length > 0
       throw new Error("Command already added. Call override() to override it")


Minor fix for when grade is ready to submit

--- lms/static/coffee/src/staff_grading/staff_grading.coffee
+++ lms/static/coffee/src/staff_grading/staff_grading.coffee
@@ -234,7 +234,8 @@

   graded_callback: () =>
     @grade = $("input[name='grade-selection']:checked").val()
-
+    if score == undefined
+      return
     # check to see whether or not any categories have not been scored
     num_categories = $('table.rubric tr').length
     for i in [0..(num_categories-1)]


Tests: Component listing no longer sends undefined

Must have changed in recent version of noflo-runtime-base?

--- spec/network.coffee
+++ spec/network.coffee
@@ -254,23 +254,18 @@
               required: false
               addressable: false
               description: 'Packet to be printed through console.log'
-              values: undefined
-              default: undefined
             ,
               id: 'options'
               type: 'object'
               required: false
               addressable: false
               description: 'Options to be passed to console.log'
-              values: undefined
-              default: undefined
             ]
             chai.expect(msg.payload.outPorts).to.eql [
               id: 'out'
               type: 'all'
               required: false
               addressable: false
-              description: undefined
             ]
             window.removeEventListener 'message', listener, false
             done()


Fix typo

Fix typo

Closes #34

--- src/exprestive.coffee
+++ src/exprestive.coffee
@@ -53,7 +53,7 @@
       @controllers.applyAction {controllerName, actionName, args}

-  # Reterns true if the passed option is its default value
+  # Returns true if the passed option is its default value
   optionIsDefault: (optionName) ->
     @options[optionName] is Exprestive.defaultOptions[optionName]


hubot now case insensitive

hubot now case insensitive

--- src/hubot-lunch-at-amica.coffee
+++ src/hubot-lunch-at-amica.coffee
@@ -89,7 +89,7 @@

   robot.respond /(.*)(lunch|lounasta|ruokaa) (\w*)+/i, (res)->

-    place = res.match[3]
+    place = res.match[3].toLowerCase()

     res.send "Today at #{place}:"
     res.send ""
@@ -107,7 +107,7 @@

   robot.hear /whats for lunch at (\w*)+/i, (res)->

-    place = res.match[1]
+    place = res.match[1].toLowerCase()

     res.send "Today at #{place}:"
     getLunch res, restaurants[place] if place of restaurants


Removed the unnecessary space

Removed the unnecessary space

--- src/javascript/accordion.coffee
+++ src/javascript/accordion.coffee
@@ -87,8 +87,7 @@
             debug '開啟手風琴分頁', index, element
             module.trigger.open index
             module.set.active   index
-
-            $allModules
+            return $allModules

         close: (index) =>
             debug '關閉手風琴分頁', index, element
@@ -99,8 +98,7 @@
             if settings.closeNested
                 debug '關閉子手風琴因應設定', index, element
                 module.closeChildren()
-
-            $allModules
+            return $allModules

         closeChildren: =>
             $this.find(Selector.ACCORDION).accordion 'close all'
@@ -108,14 +106,12 @@
         closeOthers: (index) =>
             debug '關閉指定手風琴分頁以外的其他分頁', index, element
             module.closeAll()
-
-            $allModules
+            return $allModules

         closeAll: =>
             debug '關閉所有手風琴分頁', element
             module.close i for i in [0..$title.length-1]
-
-            $allModules
+            return $allModules

         toggle: (index) =>
             debug '切換手風琴分頁', index, element
@@ -126,11 +122,9 @@
                     debug '手風琴不允許閉合開啟的分頁，略過切換步驟', index, element
             else
                 module.open index
-
-            $allModules
+            return $allModules

         trigger:
-
             open: (index) =>
                 $this.trigger Event.OPENING, $content.eq(index).get()
                 $this.trigger Event.OPEN   , $content.eq(index).get()
@@ -142,7 +136,6 @@
                 $this.trigger Event.CHANGE , $content.eq(index).get()

         is:
-
             active: (index) =>
                 $title
                     .eq       index
@@ -152,7 +145,6 @@
                 not module.is.active index

         set:
-
             active: (index) =>
                 $title
                     .eq       index
@@ -170,7 +162,6 @@
                     .removeClass ClassName.ACTIVE

         bind:
-
             events: =>
                 $this.on Event.CLICK, Selector.TITLE, ->
                     debug '發生 CLICK 事件', element, @
@@ -205,12 +196,10 @@
         refresh: =>
             $title   = $this.find Selector.TITLE
             $content = $this.find Selector.CONTENT
-
-            $allModules
+            return $allModules

         destroy: =>
             debug '摧毀手風琴', element
             $this.removeData MODULE_NAMESPACE
                  .off        EVENT_NAMESPACE
-
-            $allModules+            return $allModules


test for complex graph

test for complex graph

--- test/dag.coffee
+++ test/dag.coffee
@@ -123,6 +123,47 @@

       test.done()

+    'large graph': (test) ->
+      # taken from http://stackoverflow.com/a/12790718
+      dag = new Vorrang()
+        .before(0, 7)
+        .before(0, 10)
+        .before(0, 13)
+        .before(1, 2)
+        .before(1, 9)
+        .before(1, 13)
+        .before(2, 10)
+        .before(2, 12)
+        .before(2, 13)
+        .before(2, 14)
+        .before(3, 6)
+        .before(3, 8)
+        .before(3, 9)
+        .before(3, 10)
+        .before(4, 7)
+        .before(5, 6)
+        .before(5, 7)
+        .before(5, 9)
+        .before(5, 10)
+        .before(6, 15)
+        .before(7, 14)
+        .before(8, 15)
+        .before(9, 11)
+        .before(9, 14)
+        .before(10, 14)
+
+      numbers = [0..15]
+      for number in numbers
+        test.ok dag.isIn number
+      test.ok not dag.isIn 16
+
+      test.ok hasSameElements numbers, dag.elements()
+
+      test.ok hasSameElements [0, 1, 3, 4, 5], dag.parentless()
+      test.ok hasSameElements [12, 13, 14, 11, 15], dag.childless()
+
+      test.done()
+
   'failures':

     'keep it irreflexive: can not set a -> a': (test) ->


added default titan_account to account registration

--- app/js/controllers/registration.coffee
+++ app/js/controllers/registration.coffee
@@ -42,6 +42,6 @@
         website= $scope.account.private_data.gui_data.website
     else
         website= ""
-    Wallet.wallet_account_register($scope.account.name, $scope.m.payfrom[0], {'gui_data':{'website': website}}, payrate).then (response) ->
+    Wallet.wallet_account_register($scope.account.name, $scope.m.payfrom[0], {'gui_data':{'website': website}}, payrate, "titan_account").then (response) ->
       $modalInstance.close("ok")
       $scope.p.pendingRegistration = Wallet.pendingRegistrations[$scope.account.name] = "pending"


クラスの記述位置入れ替え（ロジック変更なし）

クラスの記述位置入れ替え（ロジック変更なし）

--- src/init/index.coffee
+++ src/init/index.coffee
@@ -4,23 +4,6 @@
 #
 # --------------------------------------
 ProgressContext = require('../progress/index').ProgressContext
-
-
-# InitComponent用mixn
-@InitController =
-  getInitialState: ->
-    {}
-
-  handleSubmit: ->
-    formData = {}
-    formData.programName = @linkState('programName').value
-    formData.players = []
-    for i in [0..@props.maxPlayers]
-      val_ = @linkState('player[' + i + ']').value
-      val_ = '' if typeof val_ == "undefined"
-      formData.players.push(val_)
-
-    @dispatch('submit', formData)

 # 初期化画面用Context
@@ -40,3 +23,20 @@

     subscribe 'submit', (form) ->
       App.router.pushContext(ProgressContext, form)
+
+
+# InitComponent用mixn
+@InitController =
+  getInitialState: ->
+    {}
+
+  handleSubmit: ->
+    formData = {}
+    formData.programName = @linkState('programName').value
+    formData.players = []
+    for i in [0..@props.maxPlayers]
+      val_ = @linkState('player[' + i + ']').value
+      val_ = '' if typeof val_ == "undefined"
+      formData.players.push(val_)
+
+    @dispatch('submit', formData)


allow options

allow options

--- src/marked-brunch-static.coffee
+++ src/marked-brunch-static.coffee
@@ -1,13 +1,15 @@
 marked = require 'marked'

 class MarkedBrunchStatic
+  constructor: (@config) ->
+
   handles: /\.static\.(?:markdown|mdown|mkdn|md|mkd|mdwn|mdtxt|mdtext|text)$/

   transformPath: (filename) ->
     filename.replace /\.static\.\w+$/, '.html'

   compile: (data, filename, callback) ->
-    marked data, (err, content) ->
+    marked data, @config, (err, content) ->
       if err
         callback err
         return


Boyajian reference pointing to updated MNRAS file

--- app/pages/about/publications-page.cjsx
+++ app/pages/about/publications-page.cjsx
@@ -147,10 +147,12 @@
     },
     {slug: "zooniverse/planet-hunters"
     publications: [
-      {citation: "Planet Hunters. IX. KIC 8462852 – Where’s the flux?, Boyajian+ 2016."
-      href: "http://mnras.oxfordjournals.org/content/457/4/3988.full.pdf"},
+      {citation: "Planet Hunters X: Searching for Nearby Neighbors of 75 Planet and Eclipsing Binary Candidates from the K2 Kepler extended mission, Schmitt+ 2016."
+      href: "http://arxiv.org/pdf/1603.06945v1.pdf"},
       {citation: "Planet Hunters. VIII. Characterization of 41 Long-Period Exoplanet Candidates from Kepler Archival Data, Wang+ 2015."
       href: "http://arxiv.org/pdf/1512.02559v2.pdf"},
+      {citation: "Planet Hunters. IX. KIC 8462852 – Where’s the flux?, Boyajian+ 2015."
+      href: "http://mnras.oxfordjournals.org/content/457/4/3988.full.pdf"},
       {citation: "GALEX J194419.33+491257.0: An unusually active SU UMa-type dwarf nova with a very short orbital period in the Kepler data, Kato & Osaki 2014."
       href: "http://adsabs.harvard.edu/doi/10.1093/pasj/psu025"},
       {citation: "Planet Hunters. VI. An Independent Characterization of KOI-351 and Several Long Period Planet Candidates from the Kepler Archival Data, Schmitt+ 2014."


bugfix

bugfix

--- app/scripts/controllers/publish.coffee
+++ app/scripts/controllers/publish.coffee
@@ -23,7 +23,7 @@
         literalTypes: $scope.rdf.propertyLiteralTypes

       w = $window.open ''
-      $scope.currentMapping = $scope.sml.toSml currentMapping
+      $scope.currentMapping = $scope.sml.toSml mapping
       $scope.transform.getDumpUrl $scope.currentMapping
         .then (url) ->
           w.location = url
@@ -39,7 +39,7 @@
         literals: $scope.rdf.propertyLiteralSelection
         literalTypes: $scope.rdf.propertyLiteralTypes

-      $scope.currentMapping = $scope.sml.toSml currentMapping
+      $scope.currentMapping = $scope.sml.toSml mapping
       w = $window.open ''
       w.document.open()
       w.document.write '<pre>' + $scope.currentMapping + '</pre>'
@@ -59,5 +59,5 @@

       $scope.publishing = false
       $scope.success = true
-      $scope.currentMapping = $scope.sml.toSml currentMapping
+      $scope.currentMapping = $scope.sml.toSml mapping
       # $scope.transform.publish $scope.currentMapping


Fix call to userForId

Fix call to userForId

--- src/matteruser.coffee
+++ src/matteruser.coffee
@@ -105,7 +105,7 @@
         mmPost = JSON.parse msg.props.post

         @robot.logger.debug 'Received message from '+mmUser.username+': ' + mmPost.message
-        user = @robot.brain.userForId msg.user_id, name: mmUser.username, room: msg.channel_id
+        user = @robot.brain.userForId msg.user_id

         text = mmPost.message
         text = "#{@robot.name} #{text}" if msg.props.channel_type == 'D' and !///^#{@robot.name} ///i.test(text) # Direct message


improved interface for changeHeader for the consumer script

--- src/matteruser.coffee
+++ src/matteruser.coffee
@@ -174,11 +174,15 @@

         @client.customMessage(msg, msg.channel_id)

-    changeHeader: (channel_id, header) ->
-        return unless channel_id?
+    changeHeader: (channel, header) ->
+        return unless channel?
         return unless header?

-        @client.setChannelHeader(channel_id, header)
+        channelInfo = @client.findChannelByName(channel)
+
+        return @robot.logger.error "Channel not found" unless channelInfo?
+
+        @client.setChannelHeader(channelInfo.id, header)

 exports.use = (robot) ->
     new Matteruser robot


remove duplicate code

remove duplicate code

--- src/mkts-table.coffee
+++ src/mkts-table.coffee
@@ -378,20 +378,6 @@
     else throw new Error "(MKTS/TABLE µ4799) illegal value for valign #{rpr valign}"

 #-----------------------------------------------------------------------------------------------------------
-@_walk_most_recent_field_designations = ( me, fieldhints_and_stuff ) ->
-  ### Given a list of `[ fieldhints, x... ]` lists, return a list of `[ designation, x... ]` lists such
-  that each `designation` that resulted from each of the `fieldhints` is only kept from the instance
-  that appeared last in the list. Each `fieldhints` can produce an arbitrary number of matching field
-  designations, and later occurrences of a given field will replace earlier appearances. ###
-  R = {}
-  for [ fieldhints, stuff..., ] in fieldhints_and_stuff
-    for [ fail, field_designation, ] from @_walk_fails_and_field_designations_from_hints me, fieldhints
-      if fail? then _record me, fail
-      else          R[ field_designation ]  = stuff
-  yield [ field_designation, stuff..., ] for field_designation, stuff of R
-  yield return
-
-#-----------------------------------------------------------------------------------------------------------
 @_walk_pod_events = ( me, fieldhints_and_content_events ) ->
   for [ field_designation, content, ] from @_walk_most_recent_field_designations me, fieldhints_and_content_events
     d           = me.pod_dimensions[ field_designation ]
@@ -628,38 +614,22 @@
 @_bottom_from_rownr = ( me, rownr ) ->
   return ( @_top_from_rownr me, rownr ) + me.rowheights[ rownr ]

-#-----------------------------------------------------------------------------------------------------------
-@_fieldnames_from_hints = ( me, fieldhints ) ->
-  R = new Set()
-  for fieldhint from fieldhints
-    for cellref from IG.GRID.walk_cells_from_key me.grid, fieldhint
-      continue unless ( cellfields = me.cellfields[ cellref.cellkey ] )?
-      R.add fieldname for fieldname in cellfields
-  return [ R... ]
-

 #===========================================================================================================
 # ITERATORS
 #-----------------------------------------------------------------------------------------------------------
 @_walk_fails_and_field_designations_from_hints = ( me, fieldhints ) ->
   ### TAINT this will have to be changed to allow for named fields ###
-  count           = 0
-  fieldhints_set  = new Set ( _.trim() for _ in fieldhints.split ',' )
-  #.........................................................................................................
-  if fieldhints_set.has '*'
-    keys    = Object.keys me.fieldcells
-    count  += keys.length
-    yield [ null, key, ] for key in keys
-  #.........................................................................................................
-  else
-    seen_field_designations = new Set()
-    for fieldhint from fieldhints_set
-      continue unless ( field_designations = me.cellfields[ fieldhint ] )?
-      for field_designation in field_designations
-        continue if seen_field_designations.has field_designation
-        seen_field_designations.add field_designation
-        count += +1
-        yield [ null, field_designation, ]
+  count                   = 0
+  seen_field_designations = new Set()
+  #.........................................................................................................
+  for cell from IG.GRID.walk_cells_from_keys me.grid, fieldhints
+    continue unless ( field_designations = me.cellfields[ cell.cellkey ] )?
+    for field_designation in field_designations
+      continue if seen_field_designations.has field_designation
+      seen_field_designations.add field_designation
+      count += +1
+      yield [ null, field_designation, ]
   #.........................................................................................................
   if count is 0
     yield [ ( _fail me, 'µ5131', "field hint #{rpr fieldhints} do not match any field" ), null ]
@@ -676,6 +646,17 @@
       seen_field_designations.add field_designation
       yield field_designation
   yield return
+
+# #-----------------------------------------------------------------------------------------------------------
+# @_walk_table_edge_field_designations = ( me, edge ) ->
+#   seen_field_designations = new Set()
+#   for d from IG.GRID.walk_edge_cellrefs me.grid, edge
+#     continue unless ( field_designations = me.cellfields[ d.cellkey ] )?
+#     for field_designation in field_designations
+#       continue if seen_field_designations.has field_designation
+#       seen_field_designations.add field_designation
+#       yield field_designation
+#   yield return

 #===========================================================================================================


off by one error

off by one error

--- src/normalizer.coffee
+++ src/normalizer.coffee
@@ -145,7 +145,7 @@
     return html

   @requireLeaf: (lineNode) ->
-    unless lineNode.childNodes.length > 1
+    unless lineNode.childNodes.length > 0
       if lineNode.tagName == 'OL' || lineNode.tagName == 'UL'
         lineNode.appendChild(lineNode.ownerDocument.createElement('li'))
         lineNode = lineNode.firstChild


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/oscillator.coffee
+++ src/oscillator.coffee
@@ -1,5 +1,5 @@
 ###*
-Creates an oscillator
+Creates an oscillator function with the given

 By default, images are loaded asynchronously. A proxy object is
 returned immediately. Even though it has a draw method it will not


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/oscillator.coffee
+++ src/oscillator.coffee
@@ -3,7 +3,7 @@

 @name Oscillator
 @constructor
-@params {Number} amplitude How much to scale the osci
+@params {Number} amplitude How much to scale the oscillator function value.
 ###
 Oscillator = (options={}) ->
   {amplitude, period, offset} = options


cruft removed

cruft removed

--- src/panda-hook.coffee
+++ src/panda-hook.coffee
@@ -69,7 +69,7 @@
   # This method places a githook script into a remote repo.
   push: (options) ->
     # Generate default CoreOS post-receive githook, unless given another source.
-    console.log options
+
     exec "bash #{__dirname}/scripts/push #{options.hook_address} #{options.hook_port} #{options.repo_name} #{options.hook_name} #{options.hook_source}",
       {async: false},
       (code, output) ->


Call `super` in constructor to assign PaneModel properties

The theorist model superclass constructor will automatically assign
all declared properties, or substitute the specified default value if
no param key is present for that property.

--- src/pane-model.coffee
+++ src/pane-model.coffee
@@ -8,10 +8,11 @@
   Serializable.includeInto(this)

   @properties
+    items: -> []
     activeItem: null

-  constructor: ({@items, @activeItem}) ->
-    @items ?= []
+  constructor: ->
+    super
     @activeItem ?= @items[0]

   serializeParams: ->


Increase limit on Upcoming Fairs

Increase limit on Upcoming Fairs

--- apps/fairs/helpers/view_helpers.coffee
+++ apps/fairs/helpers/view_helpers.coffee
@@ -90,5 +90,5 @@
     upcomingFairs: _.chain(fairs)
       .filter((fair) => @isUpcoming(fair))
       .sortBy((fair) -> Date.parse(fair.start_at))
-      .take(10)
+      .take(25)
       .value()


make payment text toggleable

make payment text toggleable

--- assets/coffeescript/pupil_store.coffee
+++ assets/coffeescript/pupil_store.coffee
@@ -404,23 +404,6 @@
       orderFormContainer = "Cart-orderForm-container"
       $('#OrderType-order').addClass("Button--state-active")
       $("."+orderFormContainer).css("display","block")
-      $('label[for="form-submit"]').text('Submit Order')
-
-      $("input[class='Form-input--radio Form-checkout']").click (event)=>
-        event.preventDefault()
-        button = $(event.target)
-        id = $(button).attr('id')
-        submitTxt = if id is "order" then "Submit Order" else "Request Quote"
-        labelId = '#OrderType-'+id
-
-        orderFormActive = "Cart-orderForm--state-active"
-        if not $(labelId).hasClass("Button--state-active")
-          $("label[class^='Button-radio--lg Form-input--radioLabel--lg']").removeClass('Button--state-active')
-          $(labelId).addClass("Button--state-active")
-          if not $(orderFormContainer).hasClass(orderFormActive)
-            $("."+orderFormContainer).slideDown()
-            $("."+orderFormContainer).addClass(orderFormActive)
-          $('label[for="form-submit"]').text(submitTxt)

   eventUpdateFormValues: ->
     if $(@cartPage).length > 0
@@ -464,10 +447,19 @@
       button = $(event.target)
       input = $('#o_type')
       p_transfer = $("div[for='p-banktransfer']")
+      p_credit = $("div[for='p-credit']")
+
+      paymentText = "After you submit the request we will follow up via email with a "
+      creditCardRequest = "proforma invoice and credit card payment link."
+      bankTransferRequest = "proforma invoice and bank account details for transfer."
+      creditCardQuote = "quote and credit card payment link."
+      bankTransferQuote = "quote and bank account details for transfer."

       if $(input).val() == 'order'
         $(button).toggleClass('checkmark--active')
         $(input).val('quote')
+        submitTxt = "Submit Quote Request"
+        $('label[for="form-submit"]').text(submitTxt)

         if $(p_transfer).hasClass('Button--state-active')
           $(p_transfer).val('purchaseorder')
@@ -477,10 +469,29 @@
       else
         $(button).toggleClass('checkmark--active')
         $(input).val('order')
+        submitTxt = "Submit Order Request"
+        $('label[for="form-submit"]').text(submitTxt)
+
+      if $(button).hasClass('checkmark--active')
+        if $(p_transfer).hasClass('Button--state-active')
+          $('#payment-text').text(paymentText + bankTransferQuote)
+        if $(p_credit).hasClass('Button--state-active')
+          $('#payment-text').text(paymentText + creditCardQuote)
+      else
+        if $(p_transfer).hasClass('Button--state-active')
+          $('#payment-text').text(paymentText + bankTransferRequest)
+        if $(p_credit).hasClass('Button--state-active')
+          $('#payment-text').text(paymentText + creditCardRequest)

   eventTogglePaymentType: ->
     if $(@cartPage).length > 0
       paymentButton = $("div[for^='p-']")
+
+      paymentText = "After you submit the request we will follow up via email with a "
+      creditCardRequest = "proforma invoice and credit card payment link."
+      bankTransferRequest = "proforma invoice and bank account details for transfer."
+      creditCardQuote = "quote and credit card payment link."
+      bankTransferQuote = "quote and bank account details for transfer."

       $(paymentButton).click (event)=>
         event.preventDefault()
@@ -498,6 +509,15 @@
             $(input_transfer).val('banktransfer')
           else
             $(input_transfer).val('purchaseorder')
+
+          if buttonId == 'p-credit'
+            $('#payment-text').text(paymentText + creditCardRequest)
+            if $("#q-checkbox").hasClass('checkmark--active')
+              $('#payment-text').text(paymentText + creditCardQuote)
+          else
+            $('#payment-text').text(paymentText + bankTransferRequest)
+            if $("#q-checkbox").hasClass('checkmark--active')
+                $('#payment-text').text(paymentText + bankTransferQuote)

   eventSubmitForm: ->
     if $(@cartPage).length > 0


remove console.log

remove console.log

--- app/assets/javascripts/games.js.coffee
+++ app/assets/javascripts/games.js.coffee
@@ -9,6 +9,5 @@

   $('#summaryTabs').on 'click', 'li', (event) ->
     activeTab = $(this).find('a').attr('href')
-    console.log activeTab
     base = window.location.href.split('#')[0]
     window.location.href = base + activeTab


Restore show more state correctly on back button press.

The way we initialized the show more links would cause them to break
if you went to another post and hit the back, since the event handler
wouldn't get installed on the subsequent turbolinks:load due to teh
div hight being <= 140 px.

This also led to posts that had been expanded being de-expanded after
returning to the page.

This commit resolves both issues.

--- app/assets/javascripts/posts.js.coffee
+++ app/assets/javascripts/posts.js.coffee
@@ -20,15 +20,16 @@
     $('.show-more-link').each () ->
         link_span = $(this)
         div = link_span.parent().children(".post-body")
-#        console.log(div.height())
-#        console.log(div.html())
-        if div.height() > (14 * 10)
+        if (div.height() > (14 * 10) && div.attr("data-show-more-state") != "expanded")\
+          || div.attr("data-show-more-state") == "unexpanded"
             div.height(14 * 10)
             div.css("overflow", "hidden")
+            div.attr("data-show-more-state", "unexpanded")
             link_span.html("
Expand this post →
")
             link_span.children("a").click (event) ->
                 div.height("auto")
                 div.css("overflow", "visible")
+                div.attr("data-show-more-state", "expanded")
                 link_span.html("")
                 event.preventDefault()
                 return false


Revert keymap change

Revert keymap change

--- keymaps/darwin.cson
+++ keymaps/darwin.cson
@@ -119,8 +119,8 @@
   'cmd-right': 'editor:move-to-end-of-screen-line'
   'cmd-shift-left': 'editor:select-to-first-character-of-line'
   'cmd-shift-right': 'editor:select-to-end-of-line'
-  'alt-backspace': 'editor:delete-to-previous-word-boundary'
-  'alt-delete': 'editor:delete-to-next-word-boundary'
+  'alt-backspace': 'editor:delete-to-beginning-of-word'
+  'alt-delete': 'editor:delete-to-end-of-word'
   'ctrl-a': 'editor:move-to-first-character-of-line'
   'ctrl-e': 'editor:move-to-end-of-line'
   'ctrl-k': 'editor:cut-to-end-of-line'


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/text.coffee
+++ test/text.coffee
@@ -1,6 +1,6 @@
 module "Text"

-test "text moves up vertically"
+test "text moves up vertically", ->

 module()


Move util.calls to javascript.

Move util.calls to javascript.

--- test/util.coffee
+++ test/util.coffee
@@ -1,6 +1,7 @@
 redisLib = require 'redis'
 livedb = require '../lib'
 Memory = require '../lib/memory'
+inprocessDriver = require '../lib/inprocessdriver'

 # createRedisClient = exports.createClient = (db = new Memory()) ->
 #   createDriver = require '../lib/redisdriver'
@@ -14,10 +15,8 @@
 #   {client, redis, db, testWrapper, driver}

-createClient = exports.createClient = (db = new Memory(), createDriver = require '../lib/inprocessdriver') ->
-  #console.log "create driver:" + createDriver
+createClient = exports.createClient = (db = new Memory(), createDriver = inprocessDriver) ->
   driver = createDriver db
-  #console.log "driver itself: " + driver.rejectSubmit

   testWrapper = {name:'test'}
   sdc = {guage: (->), increment:(->), timing:(->)}
@@ -64,14 +63,12 @@
     delete ops.m.ts if ops.m
   ops

-`
-exports.calls = function(num, fn) {
-  return function(done) {
-    if (num === 0) done();
-    var n = 0;
-    fn.call(this, function() {
-      if (++n >= num) done();
-    });
-  };
-};
-`
+exports.calls = (num, fn) ->
+  (done) ->
+    done()  if num is 0
+    n = 0
+    fn.call this, ->
+      done()  if ++n >= num
+      return
+
+    return


Don’t use ambiguous \h hexadecimal character type

--- grammars/jison.cson
+++ grammars/jison.cson
@@ -382,7 +382,7 @@
   numbers:
     patterns: [
       {
-        match: "(0[Xx])(\\h+)"
+        match: "(0[Xx])([0-9A-Fa-f]+)"
         captures:
           1: name: "storage.type.number.jison"
           2: name: "constant.numeric.integer.hexadecimal.jison"


Proper syntax highlighting for const and component

--- grammars/marko.cson
+++ grammars/marko.cson
@@ -407,11 +407,11 @@
         match: "\\b(this)[.](input|state)\\b"
       }
       {
-        match: "\\b(input|state|JSON|out)\\b"
+        match: "\\b(input|state|component|JSON|out)\\b"
         name: "entity.name.type"
       }
       {
-        match: "\\b(let|var)\\b"
+        match: "\\b(let|var|const)\\b"
         name: "storage.type.var.js"
       }
       {


fix: concise mode syntax highlighting

fix: concise mode syntax highlighting


use UTIL

use UTIL

--- src/protomixin.coffee
+++ src/protomixin.coffee
@@ -1,14 +1,15 @@
 Mixin = require './mixinfactory'
+UTIL = require './util'

 enable_protomixin = ->
   Function::mixinto_proto = (mixin, options) ->
     Mixin.validate_mixin(mixin)

-    for key, value of mixin when key not in HELPERS.postmixin_hooks
+    for key, value of mixin when key not in Mixin.postmixin_hooks
       @::[key] = value
     if typeof mixin.post_protomixin == 'function'
-      mixin.post_protomixin.call(@::, (HELPERS.rest_of.apply @, arguments)...)
+      mixin.post_protomixin.call(@::, (UTIL.rest_of.apply @, arguments)...)
     @


Make the location button use the full button and not just the icon

--- packages/rocketchat-ui-message/message/messageBox.coffee
+++ packages/rocketchat-ui-message/message/messageBox.coffee
@@ -179,7 +179,7 @@

 		fileUpload filesToUpload

-	'click .message-form .icon-location.location': (event, instance) ->
+	'click .message-form .geo-location': (event, instance) ->
 		roomId = @_id

 		position = RocketChat.Geolocation.get()


nginx: use case insensitive matching for hackathon redirect to hubspot

--- deployment/nginx.coffee
+++ deployment/nginx.coffee
@@ -314,17 +314,13 @@
         resolver 8.8.8.8;
       }

-      location /Hackathon {
+      location ~* /Hackathon {
         proxy_set_header      X-Real-IP       $remote_addr;
         proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;

         resolver 8.8.8.8;
         proxy_connect_timeout 10;
         proxy_pass https://teams-koding.hs-sites.com;
-      }
-
-      location /hackathon {
-        return 301 /Hackathon ;
       }

       #{createRootLocation(KONFIG)}


:bug: Make sure to update markers when stylesheets are added

Closes #51

--- lib/color-buffer-element.coffee
+++ lib/color-buffer-element.coffee
@@ -65,6 +65,9 @@
       @editorConfigChanged()

     @subscriptions.add atom.config.observe 'editor.lineHeight', =>
+      @editorConfigChanged()
+
+    @subscriptions.add atom.styles.onDidAddStyleElement =>
       @editorConfigChanged()

     @subscriptions.add @editorElement.onDidAttach => @attach()


Use ScrollView

Use ScrollView

--- lib/deprecation-cop-view.coffee
+++ lib/deprecation-cop-view.coffee
@@ -1,8 +1,8 @@
-{$$, View} = require 'atom'
+{$, $$, ScrollView} = require 'atom'
 Grim = require 'grim'

 module.exports =
-class DeprecationCopView extends View
+class DeprecationCopView extends ScrollView
   @content: ->
     @div class: 'deprecation-cop pane-item', tabindex: -1, =>
       @div class: 'tool-panel padded', =>


Added namespacing to clientizing to avoid double event handlers.

--- src/runtime.js.coffee
+++ src/runtime.js.coffee
@@ -283,6 +283,9 @@
       # arguments, then call that function twice, once for forms, once for anchors.

       applyClientize = (selector, event, validation, submission) ->
+        # namespace the event
+        event += ".mvcoffee"
+
         $searchInside.find(selector).each (index, element) ->

           customization = {}
@@ -292,6 +295,11 @@
               customization = thisCustom

           unless customization.ignore
+            # Clean off any existing version of this event so it won't fire twice.
+            # We do need to reclientize after a section of the page has been rerendered
+            # so it's good to avoid the double event handler.
+            jQuery(element).off event
+
             jQuery(element).on event, (eventObject) ->
               callback = element.id


remove old code

remove old code

--- public/coffee/old-mesh-draw.coffee
+++ public/coffee/old-mesh-draw.coffee
@@ -1,303 +0,0 @@
-MeshCanvas = do ->
-   gl = undefined
-   meshCanvas =
-      canvas: $ '<canvas/>', {'id':'meshCanvas'}
-      drawInterval: 40
-      darwLoopId: undefined
-      time: 0.0
-      acReduction: 25.5
-      ready: false
-      theMesh:
-         triangleVertex: [ # reference of original triangle shape
-            -1.0, -.5, 0.0,
-            1.0, -.5, 0.0,
-            0.0, 1.0, 0.0
-         ]
-         levelVertex: [] # modification of current level
-         vertex:[] # accumulation of vertex
-         index:[] # index elements
-
-   radians = (degrees) ->
-      degrees * Math.PI / 180
-
-   getWebGLContext = (canvas) ->
-      names = ['webgl', 'experimental-webgl', 'webkit-3d', 'moz-webgl']
-      for name in names
-        try
-          return canvas.getContext(name)
-        catch e
-          console.log('error canvas context')
-
-   # TODO: Init color buffer, vertex, normal, etc....
-   initMeshBuffer = (mesh) ->
-      # generate and bind the buffer object
-      mesh.vbo = gl.createBuffer()
-      gl.bindBuffer gl.ARRAY_BUFFER, mesh.vbo
-      gl.bufferData gl.ARRAY_BUFFER, new Float32Array(mesh.vertex), gl.DYNAMIC_DRAW # Dynamic access to the vertex
-
-      # set up attrib pointer
-      gl.enableVertexAttribArray meshCanvas.program.vertexPositionAttribute # Attrib location id pointer
-      gl.vertexAttribPointer(
-         meshCanvas.program.vertexPositionAttribute,
-         3, gl.FLOAT, false, 0, 0)
-
-      if mesh.index? && mesh.index.length > 0
-         mesh.ibo = gl.createBuffer()
-         gl.bindBuffer gl.ELEMENT_ARRAY_BUFFER, mesh.ibo
-         gl.bufferData gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(mesh.index), gl.STATIC_DRAW
-
-   addLevel = ->
-      l = (meshCanvas.theMesh.vertex.length - 3*3) / 3 # 3 float per vertex, 3 vertex
-      # a = a.splice(0, a.length - b.length).concat(b);
-      meshCanvas.theMesh.vertex = meshCanvas.theMesh.vertex.splice(0, meshCanvas.theMesh.vertex.length-meshCanvas.theMesh.levelVertex.length ).concat( meshCanvas.theMesh.levelVertex, meshCanvas.theMesh.levelVertex )
-      # calculate triangle index to draw elements
-      for v in [0..2]
-         i = v+l
-         meshCanvas.theMesh.index.push(
-            i,
-            l+(i+1)%3,
-            i+3,
-
-            i+3,
-            l+(i+1)%3,
-            l+(i+1)%3+3
-         )
-
-   initGeometry = ->
-      # theMesh
-      meshCanvas.theMesh.levelVertex = meshCanvas.theMesh.levelVertex.concat(meshCanvas.theMesh.triangleVertex)
-      meshCanvas.theMesh.vertex = meshCanvas.theMesh.vertex.concat(meshCanvas.theMesh.triangleVertex)
-      addLevel()
-      initMeshBuffer(meshCanvas.theMesh)
-
-   checkShaderError = (object, program = false) ->
-      if program and gl.isProgram object
-            success = gl.getProgramParameter object, gl.LINK_STATUS
-            throw 'Linking program error' + gl.getProgramInfoLog object unless success
-      else if gl.isShader object
-         success = gl.getShaderParameter object, gl.COMPILE_STATUS
-         throw 'could not compile shader:' + gl.getShaderInfoLog object unless success
-      else
-         throw 'Not shader or program'
-
-   compileShader = (shaderSource, shaderType) ->
-      # create the shader object
-      shader = gl.createShader shaderType
-
-      # set the shader source code
-      gl.shaderSource shader, shaderSource
-
-      # compile the shader
-      gl.compileShader shader
-
-      # check if it compiled
-      checkShaderError(shader)
-      return shader
-
-   createShaderFromScript = (scriptId) ->
-      shaderSource = document.getElementById scriptId
-      throw ('Error: scipt not found' + scriptid) unless shaderSource
-
-      # detect shaderType by scriptTag
-      shaderType = gl.VERTEX_SHADER if shaderSource.type == 'x-shader/x-vertex'
-      shaderType = gl.FRAGMENT_SHADER if shaderSource.type == 'x-shader/x-fragment'
-      throw('Error: shader type not set') unless shaderType
-
-      compileShader(shaderSource.text, shaderType)
-
-   createShaderProgram = ->
-      # create shader program
-      meshCanvas.program =
-         shaderProgram: gl.createProgram()
-         vertexPositionAttribute: undefined
-         colorPositionAttribute: undefined
-         normalPositionAttribute: undefined
-
-      # load and compile shaders
-      vertexShader = createShaderFromScript('meshVertexShader')
-      fragmentShader = createShaderFromScript('meshFragmentShader')
-
-      # attach shaders to program
-      gl.attachShader meshCanvas.program.shaderProgram, vertexShader
-      gl.attachShader meshCanvas.program.shaderProgram, fragmentShader
-
-      # link the program
-      gl.linkProgram meshCanvas.program.shaderProgram
-
-      # check if it linked
-      checkShaderError(meshCanvas.program.shaderProgram, true)
-
-      # bind the attribute locations
-      meshCanvas.program.vertexPositionAttribute = gl.getAttribLocation(
-         meshCanvas.program.shaderProgram,
-         'vposition')
-      throw ('Error: attribute not found') if meshCanvas.program.vertexPositionAttribute < 0
-
-      # TODO: generic bind and check
-      # bind uniform locations
-      meshCanvas.program.projectionMatrixUniform = gl.getUniformLocation(
-         meshCanvas.program.shaderProgram,
-         'mprojection')
-      throw ('Could not bind uniform mprojection') unless meshCanvas.program.projectionMatrixUniform?
-
-      meshCanvas.program.viewMatrixUniform = gl.getUniformLocation(
-         meshCanvas.program.shaderProgram,
-         'mview')
-      throw ('Could not bind uniform mview') unless meshCanvas.program.viewMatrixUniform?
-
-      meshCanvas.program.modelMatrixUniform = gl.getUniformLocation(
-         meshCanvas.program.shaderProgram,
-         'mmodel')
-      throw ('Could not bind uniform mmodel') unless meshCanvas.program.modelMatrixUniform?
-
-   updateVertexPos = ->
-      l = meshCanvas.theMesh.vertex.length - 3*3 # 3 float per vertex, 3 vertex
-      gl.bindBuffer gl.ARRAY_BUFFER, meshCanvas.theMesh.vbo
-      # buffer_type, array_offset, new_data
-      gl.bufferSubData gl.ARRAY_BUFFER,
-         l*4, # 3 poinrs x Vertex, 4 bytes x Float (float32 bits)
-         new Float32Array(meshCanvas.theMesh.levelVertex)
-
-   repostMeshData = ->
-      ###
-      for i,c in meshCanvas.theMesh.index
-         console.log c+' v:'+i+' ['+meshCanvas.theMesh.vertex[i+2]+', '+meshCanvas.theMesh.vertex[i+1]+', '+meshCanvas.theMesh.vertex[i+2]+']'
-      ###
-      gl.bindBuffer gl.ARRAY_BUFFER, meshCanvas.theMesh.vbo
-      gl.bufferData gl.ARRAY_BUFFER, new Float32Array(meshCanvas.theMesh.vertex), gl.DYNAMIC_DRAW
-
-      gl.bindBuffer gl.ELEMENT_ARRAY_BUFFER, meshCanvas.theMesh.ibo
-      gl.bufferData gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(meshCanvas.theMesh.index), gl.STATIC_DRAW
-
-   pushVertexPos = (data) ->
-      if meshCanvas.ready
-         meshCanvas.theMesh.levelVertex[3*(data.slaveId-1)] =
-            meshCanvas.theMesh.triangleVertex[3*(data.slaveId-1)] +
-               data.pos.y/meshCanvas.acReduction
-         meshCanvas.theMesh.levelVertex[3*(data.slaveId-1)+1] =
-            meshCanvas.theMesh.triangleVertex[3*(data.slaveId-1)+1] +
-               data.pos.x/meshCanvas.acReduction
-
-   createCamera = ->
-      # compute camera matrix using look at
-      meshCanvas.camera =
-         modelMatrix: mat4.create()
-         viewMatrix: mat4.create()
-         projectionMatrix: mat4.create()
-
-      # default position of the mesh
-      mat4.identity(meshCanvas.camera.modelMatrix) # set to identity
-      translation = vec3.create()
-      vec3.set(translation, 0, 0, 0)
-      mat4.translate(
-         meshCanvas.camera.modelMatrix,
-         meshCanvas.camera.modelMatrix,
-         translation)
-
-      # camera view (eye, center, up)
-      mat4.lookAt(
-         meshCanvas.camera.viewMatrix,
-         [0, 0, 2],
-         [0, 0, 1],
-         [0, 1, 0])
-
-      # world projection (fov, aspect, near, far)
-      mat4.perspective(
-         meshCanvas.camera.projectionMatrix,
-         radians(70),
-         meshCanvas.aspect,
-         0.1, 100)
-
-   calculateCamera = ->
-      # camera view (eye, center, up)
-      mat4.lookAt(
-         meshCanvas.camera.viewMatrix,
-         [Math.sin(meshCanvas.time)*5.5, Math.cos(meshCanvas.time)*5.5, 1.2+meshCanvas.time/2.0],
-         [0, 0, meshCanvas.time/2.0],
-         [0, 1, 0])
-
-   setShaderCamera = ->
-      calculateCamera()
-      gl.uniformMatrix4fv(
-         meshCanvas.program.projectionMatrixUniform,
-         false,
-         meshCanvas.camera.projectionMatrix)
-
-      gl.uniformMatrix4fv(
-         meshCanvas.program.viewMatrixUniform,
-         false,
-         meshCanvas.camera.viewMatrix)
-
-      gl.uniformMatrix4fv(
-         meshCanvas.program.modelMatrixUniform,
-         false,
-         meshCanvas.camera.modelMatrix)
-
-   draw = ->
-      # clear BG as black
-      gl.clear gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT
-      gl.useProgram meshCanvas.program.shaderProgram
-      setShaderCamera()
-      updateVertexPos()
-      gl.bindBuffer gl.ARRAY_BUFFER, meshCanvas.vbo
-#      gl.drawArrays(gl.TRIANGLES, 0, meshCanvas.vertex.length/3)
-      gl.drawElements gl.LINE_STRIP, meshCanvas.theMesh.index.length, gl.UNSIGNED_SHORT, 0
-      return
-
-   updateTime = ->
-      meshCanvas.time += 0.01
-      # increase height of level
-      for i in [0..2]
-         meshCanvas.theMesh.levelVertex[i*3+2] = meshCanvas.time/3.0
-      requestAnimationFrame draw
-      return
-
-   loadResources = ->
-      createShaderProgram()
-      initGeometry()
-      createCamera()
-      # TODO: remove hack
-      setInterval () ->
-         addLevel()
-         repostMeshData()
-      , 300
-      return
-
-   setUpRender = ->
-      gl.clearColor 0.0, 0.0, 0.0, 1.0
-      # enable alpha
-      gl.blendFunc gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA
-      # near things obscure far things
-      gl.depthFunc gl.LEQUAL
-
-      # 3D z geometry
-      gl.enable gl.DEPTH_TEST
-      # setShaderLight();
-
-      meshCanvas.drawLoopId = setInterval(updateTime, meshCanvas.drawInterval)
-
-   init = ->
-      $('body').prepend(meshCanvas.canvas)
-
-      canvas = meshCanvas.canvas[0]
-      canvas.width = window.innerWidth
-      canvas.height = window.innerHeight
-
-      meshCanvas.aspect = window.innerWidth / window.innerHeight
-
-      gl = getWebGLContext(canvas)
-      console.log('webgl not working') unless gl
-
-      try
-         loadResources()
-      catch e
-         return console.log 'Error loading sources\n', e
-
-      meshCanvas.ready = true
-      # if the resources are loaded and running
-      setUpRender()
-
-   return {
-      init,
-      pushVertexPos
-   }


chat: make preview icons bigger (so people over 40 can see them) and consistently light

--- src/smc-webapp/editor_chat.cjsx
+++ src/smc-webapp/editor_chat.cjsx
@@ -868,13 +868,13 @@
                 <Col xs={10} sm={9}>
                     <ListGroup fill>
                         <ListGroupItem style={@preview_style}>
-

+

                                 <Icon name='times'/>

                                 <Markdown value={value}/>

-

+

                                 Preview (press Shift+Enter to send)

                         </ListGroupItem>
@@ -890,7 +890,10 @@
             Enable chat preview

-

+        # The 20px margin is basically a hack because the scrollbar is right on top of the icon otherwise.
+

             <Tip title='Message Preview' tip={tip} placement='left'>
                 <Icon name='eye'/>
             </Tip>


editor preview/history polish

editor preview/history polish

--- src/smc-webapp/editor_chat.cjsx
+++ src/smc-webapp/editor_chat.cjsx
@@ -18,6 +18,15 @@
 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 ###############################################################################
+
+###
+AUTHORS:
+
+  - William Stein
+  - Harald Schilly
+  - Simon Luu
+  - John Jeng
+###

 ###
 Chat message JSON format:
@@ -294,15 +303,21 @@
     show_history: ->
         #No history for mobile, since right now messages in mobile are too clunky
         if not IS_MOBILE
-

-                <Icon name='history'/>
+

+                <Tip title='Message History' tip='Show history of editing of this message.'>
+                    <Icon name='history'/>
+                </Tip>

     hide_history: ->
         #No history for mobile, since right now messages in mobile are too clunky
         if not IS_MOBILE
-

-                <Icon name='history'/>
+

+                <Tip title='Message History' tip='Hide history of editing of this message.'>
+                    <Icon name='history'/> Hide History
+                </Tip>

     disable_history: ->
@@ -737,7 +752,7 @@
         background   : '#f5f5f5'
         fontSize     : '14px'
         borderRadius : '10px 10px 10px 10px'
-        borderColor  : '#000'
+        boxShadow    : '#666 3px 3px 3px'
         paddingBottom: '20px'

     is_at_bottom: ->
@@ -834,7 +849,7 @@
                                 <Markdown value={value}/>

-                                This is a preview of your message
+                                Preview (press Shift+Enter to send)

                         </ListGroupItem>

  {#This div tag fixes a weird bug where
 tags would be rendered below the <ListGroupItem>}
@@ -846,44 +861,44 @@

     render_preview_button_on: ->
         tip =
-            Toggles message preview on
+            Currently off.  Click to turn on.

         <Button ref='on' className='smc-big-only' onClick={@button_on_click}>
-            <Tip title='Toggle Preview On' tip={tip}>
+            <Tip title='Message Preview' tip={tip} placement='left'>
+                <Icon name='toggle-off'/> Preview
+            </Tip>
+        </Button>
+
+    render_preview_button_off: ->
+        tip =
+            Currently on.  Click to turn off.
+
+
+        <Button ref='off' className='smc-big-only' onClick={@button_off_click}>
+            <Tip title='Message Preview' tip={tip} placement='left'>
                 <Icon name='toggle-on'/> Preview
             </Tip>
         </Button>

-    render_preview_button_off: ->
-        tip =
-            Toggles message preview off
-
-
-        <Button ref='off' className='smc-big-only' onClick={@button_off_click}>
-            <Tip title='Toggle Preview Off' tip={tip}>
-                <Icon name='toggle-off'/> Preview
-            </Tip>
-        </Button>
-
     render_timetravel_button: ->
         tip =
-            Redirects to the history of the sage-chat
+            Browse all versions of this chatroom.

         <Button onClick={@show_timetravel} bsStyle='info'>
-            <Tip title='TimeTravel Button' tip={tip}>
+            <Tip title='TimeTravel Button' tip={tip}  placement='left'>
                 <Icon name='history'/> TimeTravel
             </Tip>
         </Button>

     render_bottom_button: ->
         tip =
-            Scrolls the chat to the the bottom
+            Scrolls the chat to the bottom

         <Button onClick={@scroll_to_bottom}>
-            <Tip title='Scroll to Bottom Button' tip={tip}>
+            <Tip title='Scroll to Bottom Button' tip={tip}  placement='left'>
                 <Icon name='arrow-down'/> Bottom
             </Tip>
         </Button>
@@ -926,8 +941,9 @@
                         <ButtonGroup>
                             {@render_timetravel_button()}
                             {@render_bottom_button()}
-                            {@render_preview_button_on() if @state.preview_button}
-                            {@render_preview_button_off() if not @state.preview_button}
+                            {#Disabled -- see https://github.com/sagemathinc/smc/issues/794}
+                            {#@render_preview_button_on() if @state.preview_button}
+                            {#@render_preview_button_off() if not @state.preview_button}
                         </ButtonGroup>
                     </Col>
                 </Row>


More wording

More wording

--- lib/notification-element.coffee
+++ lib/notification-element.coffee
@@ -99,7 +99,7 @@
           issueButton.textContent = "View Issue"
           fatalNotification.textContent += " This issue has already been reported."
         else
-          fatalNotification.textContent += " You can help by creating an issue."
+          fatalNotification.textContent += " You can help by creating an issue. Please explain what actions triggered this error."

       toolbar = document.createElement('div')
       toolbar.classList.add('btn-toolbar')


Bug fix

Bug fix

--- lib/project-manager-view.coffee
+++ lib/project-manager-view.coffee
@@ -22,7 +22,7 @@
   toggle: (projectManager) ->
     @projectManager = projectManager
     if @hasParent()
-      @detach()
+      @cancel()
     else
       @attach()


converting over modal

converting over modal

--- src/tags/modal.coffee
+++ src/tags/modal.coffee
@@ -1,26 +1,28 @@
-View = require '../view'
-modalHTML = require '../../templates/modal'
-modalCSS = require '../../css/modal'
-socialIcons = require '../../css/socialIcons'
+riot = require 'riot'

-$ ()->
-  $('head')
-    .append($("<style>#{ modalCSS }</style>"))
-    .append($("<style>#{ socialIcons }</style>"))
+crowdcontrol = require 'crowdcontrol'
+Events = crowdcontrol.Events
+View = crowdcontrol.view.View

-module.exports = new View 'modal', modalHTML, (opts)->
-  close = ()->
+class Modal extends View
+  html: require '../../templates/modal.jade'
+  js: (opts)->
+    @waitRef = opts.config.waitRef
+    $(document).on('keydown', @closeOnEscape)
+
+  close: ()->
     $('modal').removeClass('crowdstart-active')

-  waitRef = opts.config.waitRef
-  @closeOnClickOff = (event)->
-    if waitRef.waitId == 0 && $(event.target).hasClass('crowdstart-modal') || $(event.target).parent().hasClass('crowdstart-modal-target')
-      close()
+  closeOnClickOff: (event)->
+    if @waitRef.waitId == 0 &&
+    $(event.target).hasClass('crowdstart-modal') ||
+    $(event.target).parent().hasClass('crowdstart-modal-target')
+      @close()
     else
       return true # bubble

-  @closeOnEscape = (event)->
+  closeOnEscape: (event)->
     if event.which == 27
-      close()
+      @close()

-  $(document).on('keydown', @closeOnEscape)
+module.exports = Modal


Refactoring

Refactoring

--- src/spine/node.coffee
+++ src/spine/node.coffee
@@ -19,76 +19,74 @@
 		MULTI: 'multi'

 	@activate: (node) ->
-		unless @lineageIsBusy node
-			if !node.isActive()
-				parent = node.getParent()
-
-				if parent
-					if parent.isActive()
-						# We only care about sibling states if the parent is in exlusive mode.
-						# Multi mode is usful in implementations like lists, where it's desired
-						# to mange the transitions of many concurrent children.
-						if parent.mode == Node.Modes.EXCLUSIVE
-							siblings = parent.getChildren()
-							for sibling in siblings
-								if sibling.isActive()
-									sibling.onDeactivatedAction = @createAction sibling, 'activate'
-									return ControllerHelper.deactivate(sibling)
-
-					else
-						parent.setOnActivatedAction new ControllerAction(c, ControllerAction.TYPE_ACTIVATE)
-						return ControllerHelper.activate parent
-
-				node.attemptTransition Node.Transitions.ACTIVATE
+		return if @lineageIsBusy(node) or node.isActivated()
+
+		if node.parent
+			if node.parent.isActivated()
+				if parent.mode == Node.Modes.EXCLUSIVE
+					if sibling = parent.activatedChildren()[0]
+						sibling.onDeactivatedAction =
+							node: node
+							transition: Node.Transitions.ACTIVATE
+						return Node.deactivate sibling
+			else
+				parent.onActivatedAction =
+					node: node
+					transition: Node.Transitions.ACTIVATE
+				return Node.activate parent
+
+		node.attemptTransition Node.Transitions.ACTIVATE

 	@deactivate: (node) ->
-		unless @lineageIsBusy(c)
-			if node.isActive()
-				children = c.getChildren()
-				for child in children
-					if child.isActive()
-						child.setOnDeactivatedAction new ControllerAction(c, ControllerAction.TYPE_DEACTIVATE)
-						return ControllerHelper.deactivate(child)
-
-				node.attemptTransition Node.Transitions.DEACTIVATE
+		if node.isActive() and not @lineageIsBusy(node)
+			if node.mode == Node.Modes.EXCLUSIVE
+				if child = node.activatedChildren()[0]
+				child.onDeactivatedAction =
+					node: node
+					transition: Node.Transitions.DEACTIVATE
+				return ControllerHelper.deactivate(child)
+
+			else if node.mode == Node.Modes.MULTI
+				for child in node.activatedChildren()
+					ControllerHelper.deactivate(child)
+
+			node.attemptTransition Node.Transitions.DEACTIVATE

 	@toggle: (node) ->
-		if node.isActive()
+		if node.isActivated()
 			return @deactivate node
 		else
 			return @activate node

-	@lineageIsBusy: (node)->
-		parent = node.getParent()
-
-		if parent
+	@lineageIsBusy: (node)->
+		if parent = node.getParent()
 			return true if parent.isBusy()
 			while parent = parent.getParent()
 				return true if parent.isBusy()
-
-
+
+	### FIX FIX FIX ###
 	@onNodeActivated: (node)->
-		action = node.getOnActivatedAction()
-
-		if action
+		if action = node.onActivatedAction
 			if action.getType() == ControllerAction.TYPE_ACTIVATE
 				ControllerHelper.activateController(action.getController())

+	### FIX FIX FIX ###
 	@onNodeDeactivated: (node)->
-		action = node.getOnDeactivatedAction()
-
-		if action
+		if action = node.getOnDeactivatedAction()
 			if action.getType() == ControllerAction.TYPE_DEACTIVATE
 				ControllerHelper.deactivateController(action.getController())
 			else if action.getType() == ControllerAction.TYPE_ACTIVATE
 				ControllerHelper.activateController(action.getController())

-
 	# instance

+	id: null
 	parent: null
 	children: []

+	onAactivatedAction: null
+	onDeactivatedAction: null
+
 	constructor: (opts={})->

 		@mode = options.mode ||= Node.Modes.EXCLUSIVE
@@ -135,13 +133,47 @@
 		@children.push node

 	removeChild: (node) ->
-		@children = @children.filter (a) -> node isnt a
-
+		@children = @children.filter (a) -> a isnt node
+
+	activatedChildren: ->
+		@children().filter (n) -> n.isActivated()
+
+	childById: (id) ->
+		@children.filter((n) -> n.id == id)[0]
+
+	getDescendantById: (id) ->
+		child = @getChildById(id)
+		if child
+			return child
+
+		for child in @children
+			descendant = child.getDescendantById(id)
+			if descendant
+				return descendant
+
 	siblings: () ->
-		# @edges.filter((edge) -> edge.type == Node.Predecessor).map((edge)-> node) #flatten?
+		if @parent
+			return @parent.children.filter (n)-> n isnt @
+
+		return []

 	attemptTransition: (transition) ->
 		@sm().attemptTransition transition
+
+	isActivated: ->
+		@sm().currentState == Node.States.ACTIVATED
+
+	isTransitioning: ->
+		@sm().nextState != null
+
+	isBusy: ->
+		return true if @isTransitioning()
+
+		if @mode == 'exclusive'
+			return true if @onActivatedAction or @onDeactivatedAction
+			return true if @children.filter((n) -> n.isBusy()).length > 0
+
+		return false

 	beforeActivate: ->


Fix redirects for cf problems

Fix redirects for cf problems

--- client/components/LangCorrector.coffee
+++ client/components/LangCorrector.coffee
@@ -10,9 +10,9 @@
         return url
     url = stripLabel(url)
     if lang == "ru"
-        return url.replace("A", "А").replace("B", "Б").replace("C", "В").replace("D", "Г")
+        return url #.replace("A", "А").replace("B", "Б").replace("C", "В").replace("D", "Г")
     else
-        return url.replace("А", "A").replace("Б", "B").replace("В", "C").replace("Г", "D") + "!en"
+        return url + "!en" #.replace("А", "A").replace("Б", "B").replace("В", "C").replace("Г", "D") + "!en"

 export default LangCorrector = withLang withRouter (props) ->
     url = props.location.pathname
@@ -20,4 +20,4 @@
     if url != newUrl
         <Redirect to={newUrl}/>
     else
-        props.children+        props.children


:lipstick: Group initialize lines

:lipstick: Group initialize lines

--- lib/grammar-selector-view.coffee
+++ lib/grammar-selector-view.coffee
@@ -9,9 +9,8 @@
     @addClass('grammar-selector from-top overlay')
     @list.addClass('mark-active')

+    @autoDetect = name: 'Auto Detect'
     @currentGrammar = @editor.getGrammar()
-
-    @autoDetect = name: 'Auto Detect'
     @currentGrammar = @autoDetect if @currentGrammar is atom.syntax.nullGrammar

     @command 'grammar-selector:show', =>


client: home: started using headerize/sectionize on utilitities

--- client/home/lib/utilities/index.coffee
+++ client/home/lib/utilities/index.coffee
@@ -1,23 +1,8 @@
-kd                      = require 'kd'
-HomeUtilitiesKD         = require './homeutilitieskd'
-HomeUtilitiesDesktopApp = require './homeutilitiesdesktopapp'
-
-
-SECTIONS =
-  'KD CLI'          : HomeUtilitiesKD
-  'Koding OS X App' : HomeUtilitiesDesktopApp
-
-header = (title) ->
-  new kd.CustomHTMLView
-    tagName  : 'header'
-    cssClass : 'HomeAppView--sectionHeader'
-    partial  : title
-
-section = (name) ->
-  new (SECTIONS[name] or kd.View)
-    tagName  : 'section'
-    cssClass : "HomeAppView--section #{kd.utils.slugify name}"
-
+kd                                     = require 'kd'
+sectionize                             = require '../commons/sectionize'
+headerize                              = require '../commons/headerize'
+HomeUtilitiesKD                        = require './homeutilitieskd'
+HomeUtilitiesDesktopApp                = require './homeutilitiesdesktopapp'

 module.exports = class HomeUtilities extends kd.CustomScrollView

@@ -27,8 +12,13 @@

     super options, data

-    @wrapper.addSubView header  'KD CLI'
-    @wrapper.addSubView section 'KD CLI'
+    @wrapper.addSubView headerize  'KD CLI'
+    @wrapper.addSubView sectionize 'KD CLI', HomeUtilitiesKD

-    @wrapper.addSubView header  'Koding OS X App'
-    @wrapper.addSubView section 'Koding OS X App'
+    @wrapper.addSubView headerize  'Koding OS X App'
+    @wrapper.addSubView sectionize 'Koding OS X App', HomeUtilitiesDesktopApp
+
+
+
+
+


Java dep in zookeeper

Java dep in zookeeper

--- actions/hdp_zookeeper.coffee
+++ actions/hdp_zookeeper.coffee
@@ -3,9 +3,11 @@

 module.exports = []
 module.exports.push 'histi/actions/yum'
+module.exports.push 'histi/actions/java'

 module.exports.push module.exports.configure = (ctx) ->
   require('./hdp_core').configure ctx
+  require('./java').configure ctx
   ctx.config.hdp.zookeeper_myid ?= null
   ctx.config.hdp.zookeeper_user ?= 'zookeeper'
   ctx.config.hdp.zookeeper_data_dir ?= '/var/zookeper/data/'
@@ -61,7 +63,8 @@
   @name 'HDP ZooKeeper # Configure'
   modified = false
   hosts = (ctx.config.servers.filter (s) -> s.hdp?.zookeeper).map (s) -> s.host
-  { java_home, hadoop_group,
+  {java_home} = ctx.config.java
+  { hadoop_group,
     zookeeper_user, zookeeper_data_dir, zookeeper_pid_dir, zookeeper_log_dir,
     zookeeper_myid
   } = ctx.config.hdp


Use CompositeDisposable instead of Subscriber mixin

--- lib/markdown-preview-view.coffee
+++ lib/markdown-preview-view.coffee
@@ -1,5 +1,6 @@
 path = require 'path'

+{CompositeDisposable} = require 'atom'
 {$, $$$, ScrollView} = require 'atom'
 _ = require 'underscore-plus'
 fs = require 'fs-plus'
@@ -15,18 +16,21 @@
   constructor: ({@editorId, @filePath}) ->
     super

+    @disposables = new CompositeDisposable
+
+    unless @editorId?
+      if atom.workspace?
+        @subscribeToFilePath(@filePath)
+      else
+        @disposables.add atom.packages.onDidActivateAll =>
+          @subscribeToFilePath(@filePath)
+
   afterAttach: ->
     return if @attached

     @attached = true
     if @editorId?
       @resolveEditor(@editorId)
-    else
-      if atom.workspace? and atom.workspaceView?
-        @subscribeToFilePath(@filePath)
-      else
-        @subscribe atom.packages.once 'activated', =>
-          @subscribeToFilePath(@filePath)

   beforeRemove: ->
     @attached = false
@@ -37,7 +41,7 @@
     editorId: @editorId

   destroy: ->
-    @unsubscribe()
+    @disposables.dispose()

   subscribeToFilePath: (filePath) ->
     @file = new File(filePath)
@@ -61,7 +65,7 @@
     if atom.workspace? and atom.workspaceView?
       resolve()
     else
-      @subscribe atom.packages.onDidActivateAll(resolve)
+      @disposables.add atom.packages.onDidActivateAll(resolve)

   editorForId: (editorId) ->
     for editor in atom.workspace.getTextEditors()
@@ -69,8 +73,8 @@
     null

   handleEvents: ->
-    @subscribe atom.grammars.onDidAddGrammar _.debounce((=> @renderMarkdown()), 250)
-    @subscribe atom.grammars.onDidUpdateGrammar _.debounce((=> @renderMarkdown()), 250)
+    @disposables.add atom.grammars.onDidAddGrammar _.debounce((=> @renderMarkdown()), 250)
+    @disposables.add atom.grammars.onDidUpdateGrammar _.debounce((=> @renderMarkdown()), 250)

     atom.commands.add @element,
       'core:move-up': =>
@@ -100,17 +104,17 @@
         pane.activateItem(this)

     if @file?
-      @subscribe @file.onDidChange(changeHandler)
-    else if @editor?
-      @subscribe @editor.getBuffer().onDidStopChanging =>
+      @disposables.add @file.onDidChange(changeHandler)
+    else if @editor?
+      @disposables.add @editor.getBuffer().onDidStopChanging =>
         changeHandler() if atom.config.get 'markdown-preview.liveUpdate'
-      @subscribe @editor.onDidChangePath => @trigger 'title-changed'
-      @subscribe @editor.getBuffer().onDidSave =>
+      @disposables.add @editor.onDidChangePath => @trigger 'title-changed'
+      @disposables.add @editor.getBuffer().onDidSave =>
         changeHandler() unless atom.config.get 'markdown-preview.liveUpdate'
-      @subscribe @editor.getBuffer().onDidReload =>
+      @disposables.add @editor.getBuffer().onDidReload =>
         changeHandler() unless atom.config.get 'markdown-preview.liveUpdate'

-    @subscribe atom.config.onDidChange 'markdown-preview.breakOnSingleNewline', changeHandler
+    @disposables.add atom.config.onDidChange 'markdown-preview.breakOnSingleNewline', changeHandler

   renderMarkdown: ->
     @showLoading()


implement `$mktscript()` to parse symbolic output from subroutine calls


make sure to clear user to blank on logout complete

--- src/user/model.coffee
+++ src/user/model.coffee
@@ -11,9 +11,11 @@
   name: null
   profile_url: null
   courses: []
+  _course_data: []
+  isLoaded: false
+  isLoggingOut: false

 User =
-  isLoaded: false
   channel: new EventEmitter2 wildcard: true

   update: (data) ->
@@ -100,5 +102,4 @@
 # start out as a blank user
 _.extend(User, BLANK_USER)

-
 module.exports = User


Set audio player volume 1, when media is started

--- js/media/audioplayer/audioplayer.coffee
+++ js/media/audioplayer/audioplayer.coffee
@@ -23,7 +23,9 @@
       # 'timeLeft'
     ]
   play: ->
-    @_mediaElement.play() if @_mediaElement?
+    if @_mediaElement?
+      @_mediaElement.setVolume( 1 )
+      @_mediaElement.play()
     @_playStopButton.setLabel(@options.stopLabel) if @_playStopButton?
     @_playPauseButton.setLabel(@options.pauseLabel) if @_playPauseButton?
   pause: ->


added keycloak to karma.cof

added keycloak to karma.cof

--- admin/test/karma.conf.coffee
+++ admin/test/karma.conf.coffee
@@ -27,6 +27,7 @@
       'bower_components/AngularJS-Toaster/toaster.js'
       'bower_components/angular-ui-select2/src/select2.js'
       'bower_components/ng-table/ng-table.js'
+      'bower_components/keycloak/dist/keycloak.js'
       'app/scripts/**/*.coffee'
       'test/mock/**/*.coffee'
       'test/spec/**/*.coffee'


Remove console.log

Remove console.log

--- lib/Refactor.coffee
+++ lib/Refactor.coffee
@@ -55,7 +55,6 @@
   }, @parentNode, @depth = 0, @type = 'body') ->

     @range = locationDataToRange locationData
-    console.log @range
     @children = []
     @params = []


Refactor render method for readability

Refactor render method for readability

Test Plan:
Toggled blame and it still works

--- lib/views/blame-list-view.coffee
+++ lib/views/blame-list-view.coffee
@@ -5,33 +5,35 @@

 BlameListLinesComponent = React.createClass
-  render: ->
-    filePath = atom.workspace.activePaneItem.getPath()
-    remoteUrl = atom.project.getRepo()?.getOriginUrl(filePath)
-
+  # makes background color alternate by commit
+  _addAlternatingBackgroundColor: (lines) ->
     bgClass = null
     lastHash = null
-    lines = for ann in @props.annotations
-      args = _.clone ann  # clone so we can modify it
-
-      # url to open diff
-      args['url'] = remoteUrl
-
-      # alternating background colour by commit
-      bgClass = if ann.noCommit
+    for line in lines
+      bgClass = if line.noCommit
         ''
-      else if ann.hash is lastHash
+      else if line.hash is lastHash
         bgClass
       else if bgClass is 'line-bg-lighter'
         'line-bg-darker'
       else
         'line-bg-lighter'
-      args['backgroundClass'] = bgClass
-      lastHash = ann.hash
+      line['backgroundClass'] = bgClass
+      lastHash = line.hash
+    lines

-      # finally, render the line
-      BlameLineComponent(args)
-    div null, lines
+  render: ->
+    # clone so it can be modified
+    lines = _.clone @props.annotations
+
+    # add url to open diff
+    filePath = atom.workspace.activePaneItem.getPath()
+    remoteUrl = atom.project.getRepo()?.getOriginUrl(filePath)
+    l['url'] = remoteUrl for l in lines
+
+    @_addAlternatingBackgroundColor lines
+
+    div null, lines.map BlameLineComponent

   shouldComponentUpdate: ->
     false


make a query string for success form submission

--- assets/coffeescript/pupil_store.coffee
+++ assets/coffeescript/pupil_store.coffee
@@ -505,6 +505,21 @@
       $("#order-form").on "submit", (event)=>
         event.preventDefault()
         form = $(event.target)
+        email = $('#email_c').val()
+        input_transfer = $('#p-banktransfer')
+        input_credit = $('#p-credit')
+        q = ''
+        pType = ''
+
+        if $('#o_type').val() == 'quote'
+              q = 'q'
+            else
+              q = 'o'
+
+            if $('#p-credit').prop("checked")
+              pType = 'cc'
+            else
+              pType = 'bt'

         if $(form).parsley().isValid()
           $('label[for="form-submit"]').addClass("Button--state-inactive")
@@ -546,7 +561,7 @@

             if @readyState is 4
               if @status is 200
-                window.location.replace "#{window.location.origin}/order_success"
+                window.location.replace "#{window.location.origin}/order_success/?email=" + email + '&p=' + pType + '&q=' + q
               else
                 console.warn "Request Error: #{@statusText}"

@@ -681,7 +696,25 @@
       data = @_getOrderPermalink()
       url = window.location.origin + "/cart/?" + $.param(data)
       link = "permalink"
-      html = "
You can always revisit your order with this #{link}.
"
+      urlParams = new URLSearchParams(window.location.search);
+      email = urlParams.get('email')
+      payment = urlParams.get('p')
+      quote = urlParams.get('q')
+
+      if quote == 'o'
+        pi = 'proforma invoice'
+        order_type = 'an order'
+      else
+        pi = 'quote'
+        order_type = 'a quote'
+
+      if payment == 'cc'
+        payment_method = "Use the credit card payment link in the #{pi} to complete payment."
+      else
+        payment_method = "Use the bank account information in the #{pi} to complete payment."
+
+      html = "
#{email} will receive a confirmation email with a #{pi}.

+
#{payment_method}
"
       $(".Site-content-container.Background-img-caption-container.u-textCenter").append(html)
       # very important - clear LocalStorage after setting the link
       LocalStorage.clear()


Add abbreviations

Add abbreviations

Closes #470.

--- assets/javascripts/models/entry.coffee
+++ assets/javascripts/models/entry.coffee
@@ -66,9 +66,11 @@
     'modernizr': 'mdr'
     'moment.js': 'mt'
     'nginx': 'ngx'
+    'numpy': 'np'
     'postgresql': 'pg'
     'python': 'py'
     'ruby.on.rails': 'ror'
     'ruby': 'rb'
     'sass': 'scss'
+    'tensorflow': 'tf'
     'underscore.js': '_'


fix a typo

fix a typo

--- library/exposure/navigate.coffee
+++ library/exposure/navigate.coffee
@@ -80,7 +80,7 @@
         assert _.isFunction externed = external implement
         assert _.isObject externed.remote.meta ?= Object()
         assert ptr = endpoint: endpoint, options: options
-        logger.sily m.grey, endpoint.underline, idenity
+        logger.silly m.grey, endpoint.underline, idenity
         _.extend externed.remote.meta, ptr; externed

     # This is an external autocall routine that when invoked on the


if there is no content don't try to compile

--- lib/compiler.coffee
+++ lib/compiler.coffee
@@ -388,4 +388,5 @@

   compile_or_pass = ->
     if not @adapter.name then return @input
+    if not @content.length then return @input
     @adapter.render(@content, @opts)


cooldown finilazation

cooldown finilazation

--- src/cooldown.coffee
+++ src/cooldown.coffee
@@ -21,7 +21,7 @@

 player.I.shootTimer = 10 # => Pew! Pew!

-pla
+player.I
 </pre></code>

 @name Cooldown


Added arguments documentation to constructors.

--- lib.coffee
+++ lib.coffee
@@ -112,6 +112,9 @@
     _.extend @, @constructor.objectify '', null, (doc or {}), (@constructor?.Meta?.fields or {})

   @_Trigger: class
+    # Arguments:
+    #   fields
+    #   fields, trigger
     constructor: (@fields, @trigger) ->
       @fields ?= []

@@ -156,6 +159,8 @@
   @_ObservingField: class extends @_Field

   @_TargetedFieldsObservingField: class extends @_ObservingField
+    # Arguments:
+    #   targetDocument, fields
     constructor: (targetDocument, @fields) ->
       super()

@@ -195,6 +200,11 @@
       assert.equal @targetDocument.Meta.document.Meta, @targetDocument.Meta

   @_ReferenceField: class extends @_TargetedFieldsObservingField
+    # Arguments:
+    #   targetDocument, fields
+    #   targetDocument, fields, required
+    #   targetDocument, fields, required, reverseName
+    #   targetDocument, fields, required, reverseName, reverseFields
     constructor: (targetDocument, fields, @required, @reverseName, @reverseFields) ->
       super targetDocument, fields

@@ -239,6 +249,9 @@
     new @_ReferenceField args...

   @_GeneratedField: class extends @_TargetedFieldsObservingField
+    # Arguments:
+    #   targetDocument, fields
+    #   targetDocument, fields, generator
     constructor: (targetDocument, fields, @generator) ->
       super targetDocument, fields


Revert "Use getFirstWith when matching property, if it is available."

This reverts commit 91100b2fb7dd572deaee1bb07420d8060e446b31.

--- lib.coffee
+++ lib.coffee
@@ -14,37 +14,23 @@

   true

-# TODO: Deduplicate between base component, blaze component, and common component packages.
 createMatcher = (propertyOrMatcherOrFunction) ->
   if _.isString propertyOrMatcherOrFunction
     property = propertyOrMatcherOrFunction
     propertyOrMatcherOrFunction = (child, parent) =>
-      # If child is parent, we might get into an infinite loop if this is
-      # called from getFirstWith, so in that case we do not use getFirstWith.
-      # TODO: Leaky abstraction here. getFirstWith is not part of base component.
-      if child isnt parent and child.getFirstWith
-        !!child.getFirstWith null, property
-      else
-        property of child
+      property of child

   else if not _.isFunction propertyOrMatcherOrFunction
     assert _.isObject propertyOrMatcherOrFunction
     matcher = propertyOrMatcherOrFunction
     propertyOrMatcherOrFunction = (child, parent) =>
       for property, value of matcher
-        # If child is parent, we might get into an infinite loop if this is
-        # called from getFirstWith, so in that case we do not use getFirstWith.
-        # TODO: Leaky abstraction here. getFirstWith is not part of base component.
-        if child isnt parent and child.getFirstWith
-          childWithProperty = child.getFirstWith null, property
+        return false unless property of child
+
+        if _.isFunction child[property]
+          return false unless child[property]() is value
         else
-          childWithProperty = child if property of child
-        return false unless childWithProperty
-
-        if _.isFunction childWithProperty[property]
-          return false unless childWithProperty[property]() is value
-        else
-          return false unless childWithProperty[property] is value
+          return false unless child[property] is value

       true


Expose the subscription error.

Expose the subscription error.

--- lib.coffee
+++ lib.coffee
@@ -463,10 +463,10 @@
       onReady: =>
         @assertTrue true
         callback?()
-      onError: =>
+      onError: (error) =>
         @assertFail
           type: 'subscribe'
-          message: "Subscrption to endpoint failed, but should have succeeded."
+          message: "Subscrption to endpoint failed, but should have succeeded: #{error}"
         callback?()

   assertSubscribeFails: (endpoint, args..., callback) =>


Modes; also fix #1415 for <Enter> and the like.

--- content_scripts/vimium_frontend.coffee
+++ content_scripts/vimium_frontend.coffee
@@ -460,13 +460,15 @@
       else if (!isInsertMode() && !findMode)
         if (isPassKey keyChar)
           return handlerStack.stopBubblingAndTrue
-        if currentCompletionKeys.indexOf(keyChar) != -1 or isValidFirstKey(keyChar) or
-            # If PostFindMode is active, then we're blocking vimium's keystrokes from going into an input
-            # element.  So we should also block other keystrokes (otherwise, it's weird).
-            InsertModeBlocker.isActive()
+        if currentCompletionKeys.indexOf(keyChar) != -1 or isValidFirstKey(keyChar)
           DomUtils.suppressEvent(event)

         keyPort.postMessage({ keyChar:keyChar, frameId:frameId })
+
+  if InsertModeBlocker.isActive()
+    # If PostFindMode is active, then we're blocking vimium's keystrokes from going into an input
+    # element.  So we should also block other keystrokes (otherwise, it's weird).
+    DomUtils.suppressEvent(event)

   return true

@@ -558,10 +560,12 @@
   # TOOD(ilya): Revisit this. Not sure it's the absolute best approach.
   if (keyChar == "" && !isInsertMode() &&
      (currentCompletionKeys.indexOf(KeyboardUtils.getKeyChar(event)) != -1 ||
-      isValidFirstKey(KeyboardUtils.getKeyChar(event)) ||
-      # If PostFindMode is active, then we're blocking vimium's keystrokes from going into an input
-      # element.  So we should also block other keystrokes (otherwise, it's weird).
-      InsertModeBlocker.isActive()))
+      isValidFirstKey(KeyboardUtils.getKeyChar(event))))
+    DomUtils.suppressPropagation(event)
+    KeydownEvents.push event
+  else if InsertModeBlocker.isActive()
+    # If PostFindMode is active, then we're blocking vimium's keystrokes from going into an input
+    # element.  So we should also block other keystrokes (otherwise, it's weird).
     DomUtils.suppressPropagation(event)
     KeydownEvents.push event


Do no init Vomnibar pre-DomReady (tweak).

--- content_scripts/vimium_frontend.coffee
+++ content_scripts/vimium_frontend.coffee
@@ -438,7 +438,7 @@
   initializeTopFrame = -> # Only do this initialization once.
   # We only initialize the vomnibar in the tab's top/main frame, because it's only ever opened there.
   if DomUtils.isTopFrame()
-    DomUtils.documentReady -> Vomnibar.init()
+    DomUtils.documentReady Vomnibar.init.bind Vomnibar
   else
     # Ignore requests from other frames (we're not the top frame).
     unless request?


Animation: Update comments and remove unused properties.

--- engine/animation.coffee
+++ engine/animation.coffee
@@ -1,7 +1,3 @@
-nancheck = (v) ->
-    if v? and (v!=v or v[0]!=v[0]) then debugger
-    v
-
 {mat2, mat3, mat4, vec2, vec3, vec4, quat} = require 'gl-matrix'
 {update_ob_physics} = require './physics.coffee'
 {clamp} = window
@@ -71,7 +67,7 @@
         # TODO document and distinguish:
         # - methods that one can override (init, step)
         # - members usually assigned in step()
-        # - members used in evaluate()
+        # - members used in apply()
         # - methods for regular usage, that can be chained
         {exclude=[], start_marker, end_marker} = options or {}
         full_exclude_list = []
@@ -84,24 +80,13 @@
                 full_exclude_list.push thing
         @objects = for ob in objects when ob not in exclude then ob
         {@scene, scene: {@context}} = @objects[0]
-        # Position in animation frames, usually assigned in update(),
+        # Position in animation frames, usually assigned in step(),
         # used when evaluating the animation
         @pos = 0
-        # Final factor is calculated from weight and fade in/out
-        # usually in update(), and used when evaluating the animation.
-        # Multiplies all values of each channel
-        # and it's normalized with other animations playing the same channel
-        # so the final factor of all animations combined will always be <= 1
-        @final_factor = 1
         # Set and used when evaluating the animation to calculate frame_delta
         @last_eval = performance.now()
-        # All the rest are only used in update()
+        # All the rest are only used in step()
         @speed = 0
-        @weight = 1
-        @blendin_total = 0
-        @blendout_total = 0
-        @blendin_remaining = 0
-        @blendout_remaining = 0
         # Set start_frame and end_frame
         # from markers (if any) or from scene
         {markers_by_name, frame_start, frame_end} = @scene
@@ -172,8 +157,9 @@
                             continue
                 action = actions[strip.action]
                 scaled_pos = strip_pos/strip.scale
-                # we're ignoring strip.scale, instead we're checking
+                # we're ignoring strip.repeat, instead we're only checking that
                 # we're not exactly at the end or past it (or at the start for reversed)
+                # since the repeat is implicit in the other 5 playback attributes we use
                 if @pos < frame_end and @pos > frame_start
                     # TODO: check we're not off by one when repeating
                     scaled_pos %= action_frame_end - action_frame_start
@@ -186,13 +172,11 @@
                 # First, iterate through all animations
                 # to accumulate the result for this channel
                 blend = null
-                # TODO: use weight influence with multiple animations
-                # the goal is to normalize influence in a way
-                # there strips are always affecting 100% or 0%
-                # e.g. when it's the first animation does blend in
-                # it affects 100% when it's not zero,
-                # when two animations are blending in, both weights are normalized
-                weight = 0
+                # TODO: blender seems to behave as if the influence of the first strip
+                # is always 1 or 0, independently of other strips.
+                # we're doing this (with blend_factor = 1 below)
+                # but we want it to work across different animations
+                # (including copies of the same animation)
                 type = name = prop = ''
                 for {strip, action, pos, blend_factor} in strip_actions
                     orig_chan = action.channels[path]