Reordered tests to be more consistent with errors.

--- tests.coffee
+++ tests.coffee
@@ -2548,6 +2548,82 @@
   # Verify we are back to normal
   testDefinition test

+testAsyncMulti 'meteor-peerdb - errors for generated fields', [
+  (test, expect) ->
+    Log._intercept 3 if Meteor.isServer # Three to see if we catch more than expected
+
+    IdentityGenerators.insert
+      source: 'foobar'
+    ,
+      expect (error, identityGeneratorId) =>
+        test.isFalse error, error?.toString?() or error
+        test.isTrue identityGeneratorId
+        @identityGeneratorId = identityGeneratorId
+
+    # Sleep so that observers have time to update documents
+    Meteor.setTimeout expect(), 750
+,
+  (test, expect) ->
+    if Meteor.isServer
+      intercepted = Log._intercepted()
+
+      # One or two because it depends if the client tests are running at the same time
+      test.isTrue 1 <= intercepted.length <= 2, intercepted
+
+      # We are testing only the server one, so let's find it
+      for i in intercepted
+        break if i.indexOf(@identityGeneratorId) isnt -1
+      intercepted = EJSON.parse i
+
+      test.equal intercepted.message, "Generated field 'results' defined as an array with selector '#{ @identityGeneratorId }' was updated with a non-array value: 'foobar'"
+      test.equal intercepted.level, 'error'
+
+    @identityGenerator = IdentityGenerators.findOne @identityGeneratorId,
+      transform: null # So that we can use test.equal
+
+    test.equal @identityGenerator,
+      _id: @identityGeneratorId
+      source: 'foobar'
+      result: 'foobar'
+
+    Log._intercept 3 if Meteor.isServer # Three to see if we catch more than expected
+
+    IdentityGenerators.update @identityGeneratorId,
+      $set:
+        source: ['foobar2']
+    ,
+      expect (error, res) =>
+        test.isFalse error, error?.toString?() or error
+        test.isTrue res
+
+    # Sleep so that observers have time to update documents
+    Meteor.setTimeout expect(), 750
+,
+  (test, expect) ->
+    if Meteor.isServer
+      intercepted = Log._intercepted()
+
+      # One or two because it depends if the client tests are running at the same time
+      test.isTrue 1 <= intercepted.length <= 2, intercepted
+
+      # We are testing only the server one, so let's find it
+      for i in intercepted
+        break if i.indexOf(@identityGeneratorId) isnt -1
+      intercepted = EJSON.parse i
+
+      test.equal intercepted.message, "Generated field 'result' not defined as an array with selector '#{ @identityGeneratorId }' was updated with an array value: [ 'foobar2' ]"
+      test.equal intercepted.level, 'error'
+
+    @identityGenerator = IdentityGenerators.findOne @identityGeneratorId,
+      transform: null # So that we can use test.equal
+
+    test.equal @identityGenerator,
+      _id: @identityGeneratorId
+      source: ['foobar2']
+      result: 'foobar'
+      results: ['foobar2']
+]
+
 Tinytest.add 'meteor-peerdb - invalid documents', (test) ->
   list = _.clone Document.Meta.list

@@ -4666,12 +4742,12 @@
     test.isFalse @post, @post
 ]

-testAsyncMulti 'meteor-peerdb - errors for generated fields', [
+testAsyncMulti 'meteor-peerdb - exception while processing', [
   (test, expect) ->
     Log._intercept 3 if Meteor.isServer # Three to see if we catch more than expected

     IdentityGenerators.insert
-      source: 'foobar'
+      source: 'exception'
     ,
       expect (error, identityGeneratorId) =>
         test.isFalse error, error?.toString?() or error
@@ -4693,82 +4769,6 @@
         break if i.indexOf(@identityGeneratorId) isnt -1
       intercepted = EJSON.parse i

-      test.equal intercepted.message, "Generated field 'results' defined as an array with selector '#{ @identityGeneratorId }' was updated with a non-array value: 'foobar'"
-      test.equal intercepted.level, 'error'
-
-    @identityGenerator = IdentityGenerators.findOne @identityGeneratorId,
-      transform: null # So that we can use test.equal
-
-    test.equal @identityGenerator,
-      _id: @identityGeneratorId
-      source: 'foobar'
-      result: 'foobar'
-
-    Log._intercept 3 if Meteor.isServer # Three to see if we catch more than expected
-
-    IdentityGenerators.update @identityGeneratorId,
-      $set:
-        source: ['foobar2']
-    ,
-      expect (error, res) =>
-        test.isFalse error, error?.toString?() or error
-        test.isTrue res
-
-    # Sleep so that observers have time to update documents
-    Meteor.setTimeout expect(), 750
-,
-  (test, expect) ->
-    if Meteor.isServer
-      intercepted = Log._intercepted()
-
-      # One or two because it depends if the client tests are running at the same time
-      test.isTrue 1 <= intercepted.length <= 2, intercepted
-
-      # We are testing only the server one, so let's find it
-      for i in intercepted
-        break if i.indexOf(@identityGeneratorId) isnt -1
-      intercepted = EJSON.parse i
-
-      test.equal intercepted.message, "Generated field 'result' not defined as an array with selector '#{ @identityGeneratorId }' was updated with an array value: [ 'foobar2' ]"
-      test.equal intercepted.level, 'error'
-
-    @identityGenerator = IdentityGenerators.findOne @identityGeneratorId,
-      transform: null # So that we can use test.equal
-
-    test.equal @identityGenerator,
-      _id: @identityGeneratorId
-      source: ['foobar2']
-      result: 'foobar'
-      results: ['foobar2']
-]
-
-testAsyncMulti 'meteor-peerdb - exception while processing', [
-  (test, expect) ->
-    Log._intercept 3 if Meteor.isServer # Three to see if we catch more than expected
-
-    IdentityGenerators.insert
-      source: 'exception'
-    ,
-      expect (error, identityGeneratorId) =>
-        test.isFalse error, error?.toString?() or error
-        test.isTrue identityGeneratorId
-        @identityGeneratorId = identityGeneratorId
-
-    # Sleep so that observers have time to update documents
-    Meteor.setTimeout expect(), 750
-,
-  (test, expect) ->
-    if Meteor.isServer
-      intercepted = Log._intercepted()
-
-      # One or two because it depends if the client tests are running at the same time
-      test.isTrue 1 <= intercepted.length <= 2, intercepted
-
-      # We are testing only the server one, so let's find it
-      for i in intercepted
-        break if i.indexOf(@identityGeneratorId) isnt -1
-      intercepted = EJSON.parse i
-
       test.isTrue intercepted.message.lastIndexOf('Exception processing PeerDB fields: Error: Test exception', 0) is 0
       test.equal intercepted.level, 'error'
 ]


Fix bug in test suite due to wrong indentation

--- test/oplog.coffee
+++ test/oplog.coffee
@@ -48,10 +48,10 @@
           throw new Error err if err
           assert.strictEqual v, 1
           @db.writeOp @cName, @docName, {v:1, op:{position:2, text:'hi'}}, (err) =>
-          @db.getVersion @cName, @docName, (err, v) ->
-            throw new Error err if err
-            assert.strictEqual v, 2
-            done()
+            @db.getVersion @cName, @docName, (err, v) ->
+              throw new Error err if err
+              assert.strictEqual v, 2
+              done()

     it 'ignores subsequent attempts to write the same operation', (done) ->
       @db.writeOp @cName, @docName, {v:0, create:{type:ottypes.simple.uri}}, (err) =>


client: revert gokmens small change

client: revert gokmens small change

--- client/landing/About/team.coffee
+++ client/landing/About/team.coffee
@@ -16,11 +16,11 @@
         username  : 'gokmen'
         title     : 'Software Engineer'
       ,
+        username  : 'arslan'
+        title     : 'Software Engineer'
+      ,
         username  : 'fatihacet'
         title     : 'Front-End Engineer'
-      ,
-        username  : 'arslan'
-        title     : 'Software Engineer'
       ,
         username  : 'sent-hil'
         title     : 'Software Engineer'


Updated animationframe shims

Updated animationframe shims

--- src/core/animationframe.coffee
+++ src/core/animationframe.coffee
@@ -1,35 +1,35 @@
-do ->
-  vendors = ['ms', 'moz', 'webkit', 'o']
+vendors = ['ms', 'moz', 'webkit', 'o']

-  define 'requestAnimationFrame', ['root'], (root) ->
+define 'requestanimationframe', ['root'], (root) ->
+  {requestAnimationFrame} = root
+
+  unless requestAnimationFrame
+    for x in vendors
+      requestAnimationFrame = root["#{x}RequestAnimationFrame"]
+      break if requestAnimationFrame
+
+  unless requestAnimationFrame
     lastTime = 0
-    {requestAnimationFrame} = root

-    unless requestAnimationFrame
-      for x in vendors
-        requestAnimationFrame = root["#{x}RequestAnimationFrame"]
-        break if requestAnimationFrame
-
-    unless requestAnimationFrame
-      requestAnimationFrame = (callback, element) ->
-        currTime = Date.now()
-        timeToCall = Math.max 0, 16 - (currTime - lastTime)
-        id = root.setTimeout((-> callback(currTime + timeToCall)), timeToCall)
-        lastTime = currTime + timeToCall
-        id
-
-    requestAnimationFrame
-
-  define 'cancelAnimationFrame', ['root'], (root) ->
-    {cancelAnimationFrame} = root
-
-    unless cancelAnimationFrame
-      for x in vendors
-        cancelAnimationFrame = root["#{x}CancelAnimationFrame"] or
-          root["#{x}CancelRequestAnimationFrame"]
-        break if cancelAnimationFrame
-
-    unless cancelAnimationFrame
-      cancelAnimationFrame = (id) -> root.clearTimeout id
-
-    cancelAnimationFrame+    requestAnimationFrame = (callback, element) ->
+      currTime = performance.now() ? Date.now()
+      timeToCall = Math.max 0, 16 - (currTime - lastTime)
+      id = root.setTimeout((-> callback(currTime + timeToCall)), timeToCall)
+      lastTime = currTime + timeToCall
+      id
+
+  requestAnimationFrame
+
+define 'cancelanimationframe', ['root'], (root) ->
+  {cancelAnimationFrame} = root
+
+  unless cancelAnimationFrame
+    for x in vendors
+      cancelAnimationFrame = root["#{x}CancelAnimationFrame"] or
+        root["#{x}CancelRequestAnimationFrame"]
+      break if cancelAnimationFrame
+
+  unless cancelAnimationFrame
+    cancelAnimationFrame = (id) -> root.clearTimeout id
+
+  cancelAnimationFrame


Move text generation to module user

Move text generation to module user

Instead of returning an object which will be used to fill in the placeholders
in the template, a string is returned. This adds for flexibilty for the
module user.
In addition, not only the author's email address is passed to the callback,
the entire object, including comments' body.

--- src/discussion_analyzer.coffee
+++ src/discussion_analyzer.coffee
@@ -67,6 +67,7 @@
           break

       if !hasComment
+        discussion.comments = result.comments
         @_filtered.push discussion

       cb()
@@ -93,19 +94,18 @@
     index      = obj.index
     total      = obj.total

-    @_config.fn discussion.author_email, (err, data) =>
+    @_config.fn discussion, (err, reponseText) =>
       if err
         throw err

-      if !data?
+      if !reponseText?
         msg = "#{index} / #{total}: Author of #{discussion.html_href}"
         msg += " is not a user"
         console.log msg
         return cb()

       formData = JSON.parse JSON.stringify(@_config.formData)
-      formData.body = @_fillPlaceholders formData.body, data
-      formData.body = "#Script generated #{formData.body}"
+      formData.body = "#Script generated\n#{reponseText}"

       opts =
         url     : discussion.comments_href
@@ -143,12 +143,4 @@

       cb err, parsed

-  _fillPlaceholders: (body, dataToReplace) ->
-    for key, val of dataToReplace
-      regex = new RegExp "\{#{key}\}"
-      body = body.replace regex, val
-
-    return body
-
-
 module.exports = DiscussionAnalyzer


Correctly set and test custom image aws path

--- test/suite.coffee
+++ test/suite.coffee
@@ -298,11 +298,11 @@
         assert.equal path, image.upload.opts.aws.path + 'aa/bb/cc'
         done()

-    it 'overrides destination path prefix', ->
-      image.awsPath = 'some/path/'
+    it 'overrides destination path prefix', (done) ->
+      image.opts.awsPath = 'custom/path/'
       image.getDest (err, path) ->
         assert.ifError err
-        assert.equal path, 'some/path/aa/bb/cc'
+        assert.equal path, 'custom/path/aa/bb/cc'
         done()

   describe '#resizeVersions()', ->


Updated to double quotes

Updated to double quotes

--- source/micro.coffee
+++ source/micro.coffee
@@ -1,8 +1,10 @@
-u            = require('./micro.core.coffee')
-dom          = require('./micro.dom.coffee')
-utils        = require('./micro.utils.coffee')
-localstorage = require('./micro.localstorage.coffee')
-ajax         = require('./micro.ajax.coffee')
+"use strict"
+
+u            = require("./micro.core.coffee")
+dom          = require("./micro.dom.coffee")
+utils        = require("./micro.utils.coffee")
+localstorage = require("./micro.localstorage.coffee")
+ajax         = require("./micro.ajax.coffee")

 utils.extend u::, dom
 utils.extend u, utils, db: localstorage, ajax


Port Journal tests

Port Journal tests

--- spec/Journal.coffee
+++ spec/Journal.coffee
@@ -1,24 +1,22 @@
 if typeof process isnt 'undefined' and process.execPath and process.execPath.match /node|iojs/
   chai = require 'chai' unless chai
-  graph = require '../src/lib/Graph.coffee'
-  journal = require '../src/lib/Journal.coffee'
+  noflo = require '../src/lib/NoFlo.coffee'
 else
-  graph = require 'noflo/src/lib/Graph.js'
-  journal = require 'noflo/src/lib/Journal.js'
+  noflo = require 'noflo'

 describe 'Journal', ->
   describe 'connected to initialized graph', ->
-    g = new graph.Graph
-    g.addNode 'Foo', 'Bar'
-    g.addNode 'Baz', 'Foo'
-    g.addEdge 'Foo', 'out', 'Baz', 'in'
-    j = new journal.Journal(g)
+    g = new noflo.graph.Graph
+    g.addNode 'Foo', 'Bar'
+    g.addNode 'Baz', 'Foo'
+    g.addEdge 'Foo', 'out', 'Baz', 'in'
+    j = new noflo.journal.Journal(g)
     it 'should have just the initial transaction', ->
       chai.expect(j.store.lastRevision).to.equal 0

   describe 'following basic graph changes', ->
-    g = new graph.Graph
-    j = new journal.Journal(g)
+    g = new noflo.graph.Graph
+    j = new noflo.journal.Journal(g)
     it 'should create one transaction per change', ->
       g.addNode 'Foo', 'Bar'
       g.addNode 'Baz', 'Foo'
@@ -28,8 +26,8 @@
       chai.expect(j.store.lastRevision).to.equal 4

   describe 'pretty printing', ->
-    g = new graph.Graph
-    j = new journal.Journal(g)
+    g = new noflo.graph.Graph
+    j = new noflo.journal.Journal(g)

     g.startTransaction 'test1'
     g.addNode 'Foo', 'Bar'
@@ -60,8 +58,8 @@
       chai.expect(j.toPrettyString(0,2)).to.equal ref

   describe 'jumping to revision', ->
-    g = new graph.Graph
-    j = new journal.Journal(g)
+    g = new noflo.graph.Graph
+    j = new noflo.journal.Journal(g)
     g.addNode 'Foo', 'Bar'
     g.addNode 'Baz', 'Foo'
     g.addEdge 'Foo', 'out', 'Baz', 'in'
@@ -76,8 +74,8 @@
       chai.expect(g.nodes.length).to.equal 1

   describe 'linear undo/redo', ->
-    g = new graph.Graph
-    j = new journal.Journal(g)
+    g = new noflo.graph.Graph
+    j = new noflo.journal.Journal(g)
     g.addNode 'Foo', 'Bar'
     g.addNode 'Baz', 'Foo'
     g.addEdge 'Foo', 'out', 'Baz', 'in'
@@ -101,8 +99,8 @@
       chai.expect(g.toJSON()).to.deep.equal graphBeforeError

   describe 'undo/redo of metadata changes', ->
-    g = new graph.Graph
-    j = new journal.Journal(g)
+    g = new noflo.graph.Graph
+    j = new noflo.journal.Journal(g)
     g.addNode 'Foo', 'Bar'
     g.addNode 'Baz', 'Foo'
     g.addEdge 'Foo', 'out', 'Baz', 'in'
@@ -201,32 +199,32 @@
   j = null
   describe 'G -> B', ->
     it 'G starts out as A', (done) ->
-      graph.loadJSON JSON.parse(A), (err, instance) ->
+      noflo.graph.loadJSON JSON.parse(A), (err, instance) ->
         return done err if err
         a = instance
-        graph.loadJSON JSON.parse(A), (err, instance) ->
+        noflo.graph.loadJSON JSON.parse(A), (err, instance) ->
           return done err if err
           g = instance
-          chai.expect(graph.equivalent(a, g)).to.equal true
+          chai.expect(noflo.graph.equivalent(a, g)).to.equal true
           done()
     it 'G and B starts out different', (done) ->
-      graph.loadJSON JSON.parse(B), (err, instance) ->
+      noflo.graph.loadJSON JSON.parse(B), (err, instance) ->
         return done err if err
         b = instance
-        chai.expect(graph.equivalent(g, b)).to.equal false
+        chai.expect(noflo.graph.equivalent(g, b)).to.equal false
         done()
     it 'merge should make G equivalent to B', (done) ->
-      j = new journal.Journal(g)
+      j = new noflo.journal.Journal(g)
       g.startTransaction 'merge'
-      graph.mergeResolveTheirs g, b
+      noflo.graph.mergeResolveTheirs g, b
       g.endTransaction 'merge'
-      chai.expect(graph.equivalent(g, b)).to.equal true
+      chai.expect(noflo.graph.equivalent(g, b)).to.equal true
       done()
     it 'undoing merge should make G equivalent to A again', (done) ->
       j.undo()
-      res = graph.equivalent g, a
+      res = noflo.graph.equivalent g, a
       chai.expect(res).to.equal true
       done()

-# FIXME: add tests for graph.loadJSON/loadFile, and journal metadata
-
+# FIXME: add tests for noflo.graph.loadJSON/loadFile, and journal metadata
+


Test adding same node that we already had

--- spec/Network.coffee
+++ spec/Network.coffee
@@ -91,6 +91,13 @@
         chai.expect(n.processes.Graph.component.metadata).to.exist
         chai.expect(n.processes.Graph.component.metadata).to.be.an 'object'
         chai.expect(n.processes.Graph.component.metadata).to.eql g.getNode('Graph').metadata
+      it 'adding the same node again should be a no-op', (done) ->
+        originalProcess = n.getNode 'Graph'
+        graphNode = g.getNode 'Graph'
+        n.addNode graphNode, (err, newProcess) ->
+          return done err if err
+          chai.expect(newProcess).to.equal originalProcess
+          done()
       it 'should not contain the node after removal', (done) ->
         g.once 'removeNode', ->
           setTimeout ->


Take out constants

Take out constants

--- demos/visualizer-lazy/Grid.coffee
+++ demos/visualizer-lazy/Grid.coffee
@@ -1,17 +1,18 @@
 'use strict'
+
+COLORS =
+	BACKGROUND: '#272822'
+	PATHBACKGROUND: '#49483E'
+	GRID: '#EDF'
+	PATHINDICATOR: 'rgb(24, 155, 230)'
+	FONT: '#EDF'
+
+FONTS =
+	NORMAL: '20px Consolas, monospace'
+	SMALL: '14px Consolas, monospace'

 Grid = (@playfield, @pathSet, @canvas) ->
 	@cellSize = 36
-	@COLORS =
-		BACKGROUND: '#272822'
-		PATHBACKGROUND: '#49483E'
-		GRID: '#EDF'
-		PATHINDICATOR: 'rgb(24, 155, 230)'
-		FONT: '#EDF'
-
-	@FONTS =
-		NORMAL: '20px Consolas, monospace'
-		SMALL: '14px Consolas, monospace'

 	@canvas.width = @playfield.width * @cellSize
 	@canvas.height = @playfield.height * @cellSize
@@ -31,12 +32,12 @@

 	@hitRegions = []
 	@_setupHitRegions()
-	@arrowImages = getArrowImages @cellSize / 3, @COLORS
+	@arrowImages = getArrowImages @cellSize / 3, COLORS
 	@draw()
 	return

-getArrowImage = (size, angle, COLORS) ->
+getArrowImage = (size, angle) ->
 	canvas = document.createElement 'canvas'
 	canvas.width = size
 	canvas.height = size
@@ -54,11 +55,11 @@
 	con2d.stroke()
 	canvas

-getArrowImages = (size, COLORS) ->
-	'^': getArrowImage size, 0, COLORS
-	'<': getArrowImage size, -Math.PI / 2, COLORS
-	'v': getArrowImage size, Math.PI, COLORS
-	'>': getArrowImage size, Math.PI / 2, COLORS
+getArrowImages = (size) ->
+	'^': getArrowImage size, 0
+	'<': getArrowImage size, -Math.PI / 2
+	'v': getArrowImage size, Math.PI
+	'>': getArrowImage size, Math.PI / 2

 directions = [
@@ -137,16 +138,16 @@

 Grid::draw = ->
 	#background
-	@con2d.fillStyle = @COLORS.BACKGROUND
+	@con2d.fillStyle = COLORS.BACKGROUND
 	@con2d.fillRect 0, 0, @canvas.width, @canvas.height

 	#active path
-	@con2d.fillStyle = @COLORS.PATHBACKGROUND
+	@con2d.fillStyle = COLORS.PATHBACKGROUND
 	@highlightedPath?.list.forEach (entry) =>
 		@con2d.fillRect entry.x * @cellSize, entry.y * @cellSize, @cellSize, @cellSize

 	#chars
-	@con2d.fillStyle = @COLORS.FONT
+	@con2d.fillStyle = COLORS.FONT
 	for i in [0...@playfield.width]
 		for j in [0...@playfield.height]
 			charRaw = @playfield.getAt i, j
@@ -154,10 +155,10 @@

 			if charCode > 0
 				charPretty = if 32 <= charCode <= 126
-					@con2d.font = @FONTS.NORMAL
+					@con2d.font = FONTS.NORMAL
 					charRaw
 				else
-					@con2d.font = @FONTS.SMALL
+					@con2d.font = FONTS.SMALL
 					"##{charCode}"

 				@con2d.fillText(
@@ -174,7 +175,7 @@
 	@con2d.save()
 	@con2d.translate 0.5, 0.5

-	@con2d.strokeStyle = @COLORS.GRID
+	@con2d.strokeStyle = COLORS.GRID
 	@con2d.beginPath()
 	for i in [1...@playfield.width]
 		@con2d.moveTo i * @cellSize, 0


Fix broken url

Fix broken url

--- resources/assets/coffee/react/mp-history/content.coffee
+++ resources/assets/coffee/react/mp-history/content.coffee
@@ -49,7 +49,7 @@
           div className: 'mp-history-content__show-more-box',
             a
               className: 'mp-history-content__show-more'
-              href: laroute.route 'multiplayer.match', matches: @props.id, full: true
+              href: laroute.route('matches.show', matches: @props.id, full: true)
               Lang.get 'multiplayer.match.more-events'

         div className: 'mp-history-events',


put the JSON building inside the Applescript call due to client library doing a spawn and taking it to seperate, async process scope

--- routes/index.coffee
+++ routes/index.coffee
@@ -2,31 +2,17 @@
 router = express.Router()
 applescript = require("applescript")

-# Navigation functions
-goToSlide = (direction) ->
-  script = """
-    tell application "Microsoft PowerPoint"
-    	set slideWindow to slide show window 1 of active presentation
-    	tell active presentation
-    		set theSlideCount to count slides
-    	end tell
-      set currentSlideNumber to slide index of slide of (slide show view of slideWindow)
-    	go to #{direction} slide (slide show view of slide show window 1)
-    	{currentSlideNumber, theSlideCount}
-    end tell
-  """
-  applescript.execString script, (err, rtn) ->
-    retHash = {success: false}
-    if err
-      console.log err
-    else
-      retHash["success"] = true
-      if (Array.isArray(rtn))
-        retHash["slideIndex"] = rtn[0]
-        retHash["slideTotal"] = rtn[1]
-    return retHash
-
-
+script = (direction) -> """
+  tell application "Microsoft PowerPoint"
+  	set slideWindow to slide show window 1 of active presentation
+  	tell active presentation
+  		set theSlideCount to count slides
+  	end tell
+    set currentSlideNumber to slide index of slide of (slide show view of slideWindow)
+    go to #{direction} slide (slide show view of slide show window 1)
+  	{currentSlideNumber, theSlideCount}
+  end tell
+"""

 # GET home page.
 router.get "/", (req, res) ->
@@ -43,9 +29,19 @@
 router.post "/go/:direction", (req, res) ->
   direction = req.params.direction
   if direction in ['next', 'previous', 'first', 'last']
-    pptResult = goToSlide(direction)
-    res.json(pptResult)
-    return
+    pptResult = {success: false}
+    applescript.execString script(direction), (err, rtn) ->
+      if err
+        console.log err
+      else
+        pptResult["success"] = true
+        if (Array.isArray(rtn))
+          pptResult["slideIndex"] = rtn[0]
+          pptResult["slideTotal"] = rtn[1]
+      #  Had to put the JSON building inside the AppleScript call b/c the
+      # library we're using uses a 'spawn' call and so we end up async
+      # and without shared scope
+      res.json(pptResult)
   else
     console.error("Invalid parameter: #{direction}")
     res.send(400, 'Invalid parameters')


Hint platform

Hint platform

--- src/tools/vfilter.coffee
+++ src/tools/vfilter.coffee
@@ -29,11 +29,16 @@
 parse.ctr = Filter

 # Parse x86|x64
-parse.x64 =
-x64 = (str)->
+parse.x64 = (str)->
   return unless /^x(\d)/.test str
   '6' == RegExp.$1

 # Help strings
-parse.$6 = $6 = "[x86|x64]"
-parse.$ = "[#{keys().join '|'}] [n[.n[.n]]] #{$6}"
+alt = (arr)->
+  "[#{arr.join '|'}]"
+
+parse.$6 = $6 = do ->
+  x = ['x86','x64']
+  alt if x64 then x.reverse() else x
+
+parse.$ = "#{alt keys()} [n[.n[.n]]] #{$6}"


Updated

Updated

--- home/.atom/config.cson
+++ home/.atom/config.cson
@@ -40,3 +40,4 @@
   'sortByTitle': true
   'showPath': true
 'git-plus': {}
+'autoclose-html': {}


Enhance .atom/keymap.cson comments with references and sections.

--- home/.atom/keymap.cson
+++ home/.atom/keymap.cson
@@ -1,3 +1,4 @@
+###############################################################################
 # Your keymap
 #
 # Atom keymaps work similarly to stylesheets. Just as stylesheets use selectors
@@ -16,16 +17,23 @@
 #   'ctrl-P': 'core:move-up'
 #   'ctrl-p': 'core:move-down'
 #
+# References:
+#   https://github.com/atom/atom/tree/master/keymaps
+#   https://atom.io/docs/latest/behind-atom-keymaps-in-depth
+###############################################################################

+###############################################################################
 # map ctrl-up / ctrl-down to line movement.
 #
 # This mirrors the current vim configuration.
 #
 # The existing keymappings for these operations are ctrl-cmd-up / ctrl-cmd-down
+###############################################################################
 'body':
   'ctrl-up': 'editor:move-line-up'
   'ctrl-down': 'editor:move-line-down'

+###############################################################################
 # vim-mode-visual-block keymappings
 #
 # As of vim-mode-visual-block@0.2.4 there are no default keymappings and
@@ -33,12 +41,13 @@
 #
 # https://atom.io/packages/vim-mode-visual-block
 # https://github.com/t9md/atom-vim-mode-visual-block
+###############################################################################
 'atom-text-editor.vim-mode.visual-mode':
   'j':      'vim-mode-visual-block:j'
   'down':   'vim-mode-visual-block:j'
   'k':      'vim-mode-visual-block:k'
   'up':     'vim-mode-visual-block:k'
-  # Disable h and l. Setting these causes these key to do nothing.
+  # Disable h and l. Setting these causes these keys to do nothing.
   # 'h':      'vim-mode-visual-block:h'
   # 'left':   'vim-mode-visual-block:h'
   # 'l':      'vim-mode-visual-block:l'


forgot some menu stuff for our fellow windows / linux users

--- src/ui/views/menu.coffee
+++ src/ui/views/menu.coffee
@@ -275,25 +275,25 @@
             type:'checkbox'
             label: 'Show Conversation Thumbnails'
             checked:viewstate.showConvThumbs
-            enabled: viewstate.loggedin
+            enabled: viewstate.loggedin && !viewstate.showConvMin
             click: (it) -> action 'showconvthumbs', it.checked
         }, {
             type: 'checkbox'
             label: 'Show Animated Thumbnails'
             checked:viewstate.showAnimatedThumbs
-            enabled: viewstate.loggedin && viewstate.showConvThumbs
+            enabled: viewstate.loggedin && viewstate.showConvThumbs && !viewstate.showConvMin
             click: (it) -> action 'showanimatedthumbs', it.checked
         }, {
             type: 'checkbox'
             label: 'Show Conversation Timestamp'
             checked:viewstate.showConvTime
-            enabled: viewstate.loggedin
+            enabled: viewstate.loggedin && !viewstate.showConvMin
             click: (it) -> action 'showconvtime', it.checked
         }, {
             type: 'checkbox'
             label: 'Show Conversation Last Message'
             checked:viewstate.showConvLast
-            enabled: viewstate.loggedin
+            enabled: viewstate.loggedin && !viewstate.showConvMin
             click: (it) -> action 'showconvlast', it.checked
         }, {
             label: 'Color Scheme'


replace concat with push

replace concat with push

--- src/ui/views/menu.coffee
+++ src/ui/views/menu.coffee
@@ -34,16 +34,16 @@
 }

 templateYakYak = (viewstate) ->
-    tmp = []
-    if os.platform() == 'darwin'
-        tmp = tmp.concat [
+    tmpl = []
+    if os.platform() == 'darwin'
+        tmpl.push [
             { label: 'About YakYak', selector: 'orderFrontStandardAboutPanel:' }
             #{ type: 'separator' }
             # { label: 'Preferences...', accelerator: 'Command+,',
             # click: => delegate.openConfig() }
             { type: 'separator' }
         ]
-    tmp = tmp.concat [
+    tmpl.push [
         {
             label: 'Hide YakYak'
             accelerator: acceleratorMap['hideyakyak'][os]
@@ -52,14 +52,14 @@
     ]

     if os.platform() == 'darwin'
-        tmp = tmp.concat [{
+        tmpl.push [{
               label: 'Hide Others'
               accelerator: acceleratorMap['hideother'][os]
               selector: 'hideOtherApplications:'
         }
         { label: 'Show All', selector: 'unhideAllApplications:' }
         ]
-    tmp.concat [
+    tmpl.push [
       { type: 'separator' }
       {
           label: 'Open Inspector'
@@ -80,22 +80,22 @@
   ]

 templateEdit = (viewstate) ->
-    tmp = [
+    tmpl = [
         { label: 'Undo', accelerator: acceleratorMap['undo'][os], selector: 'undo:' }
         { label: 'Redo', accelerator: acceleratorMap['redo'][os], selector: 'redo:' }
     ]
     if os.platform() == 'darwin'
-        tmp = tmp.concat [
+        tmpl.push [
           { type: 'separator' }
           { label: 'Cut', accelerator: acceleratorMap['cut'][os], selector: 'cut:' }
           { label: 'Copy', accelerator: acceleratorMap['copy'][os], selector: 'copy:' }
           { label: 'Paste', accelerator: acceleratorMap['paste'][os], selector: 'paste:' }
           { label: 'Select All', accelerator: acceleratorMap['selectall'][os], selector: 'selectAll:' }
         ]
-    tmp
+    tmpl

 templateView = (viewstate) ->
-    tmp = [
+    tmpl = [
         {
             label: 'Conversation List'
             submenu: [
@@ -280,17 +280,17 @@
         }
     ]
     if os.platform() == 'darwin'
-        tmp = tmp.concat {
+        tmpl.push {
             label: 'Hide Dock icon'
             type: 'checkbox'
             enabled: viewstate.showtray
             checked:  viewstate.hidedockicon
             click: -> action 'togglehidedockicon'
         }
-    tmp
+    tmpl

 templateWindow = (viewstate, os) ->
-    tmp = [
+    tmpl = [
         {
             label: 'Minimize'
             accelerator: acceleratorMap['minimize'][os]
@@ -307,37 +307,24 @@
         }
     ]

-templateOsx = (viewstate) -> [
-    {
-        label: 'YakYak'
-        submenu: templateYakYak viewstate
-    }, {
-        label: 'Edit'
-        submenu: templateEdit viewstate
-    },{
-        label: 'View'
-        submenu: templateView viewstate
-    }, {
-        label: 'Window'
-        submenu: templateWindow viewstate
-    }
-  ]
-
-templateOthers = (viewstate) -> [
-    {
-        label: 'YakYak'
-        submenu: templateYakYak viewstate
-    }, {
-        label: 'Edit'
-        submenu: templateEdit viewstate
-    },{
-        label: 'View'
-        submenu: templateView viewstate
-    }
-  ]
+templateMenu = (viewstate) ->
+    tmpl = [{
+            label: 'YakYak'
+            submenu: templateYakYak viewstate
+        }, {
+            label: 'Edit'
+            submenu: templateEdit viewstate
+        },{
+            label: 'View'
+            submenu: templateView viewstate
+        }
+    ]
+    if os.platform() == 'darwin'
+        tmpl.push {
+            label: 'Window'
+            submenu: templateWindow viewstate
+        }
+    tmpl

 module.exports = (viewstate) ->
-    if os.platform() == 'darwin'
-        Menu.setApplicationMenu Menu.buildFromTemplate templateOsx(viewstate)
-    else
-        Menu.setApplicationMenu Menu.buildFromTemplate templateOthers(viewstate)
+    Menu.setApplicationMenu Menu.buildFromTemplate templateMenu(viewstate)


fix menu for animated thumbs

fix menu for animated thumbs

--- src/ui/views/menu.coffee
+++ src/ui/views/menu.coffee
@@ -52,7 +52,7 @@
                     type: 'checkbox'
                     label: 'Show Animated Thumbnails'
                     checked:viewstate.showAnimatedThumbs
-                    enabled: viewstate.loggedin && viewstate.showConvThumbs
+                    enabled: viewstate.loggedin
                     click: (it) -> action 'showanimatedthumbs', it.checked
                 }, {
                     type: 'checkbox'
@@ -290,7 +290,7 @@
                     type: 'checkbox'
                     label: 'Show Animated Thumbnails'
                     checked:viewstate.showAnimatedThumbs
-                    enabled: viewstate.loggedin && viewstate.showConvThumbs
+                    enabled: viewstate.loggedin
                     click: (it) -> action 'showanimatedthumbs', it.checked
                 }, {
                     type: 'checkbox'


update

update

--- lib/browser-plus.coffee
+++ lib/browser-plus.coffee
@@ -30,7 +30,7 @@
       if ( path.extname(uri) is '.htmlp' or
           uri.indexOf('http:') is 0 or uri.indexOf('https:') is 0 or
           uri.indexOf('localhost') is 0 or uri.indexOf('file:') is 0 or
-          uri.indexOf('browser-plus:') is 0 ) or opt.src
+          uri.indexOf('browser-plus:') is 0 ) #or opt.src
          bp = new BrowserPlusModel @,uri,opt.src
          if uri.indexOf('browser-plus://history') is 0
            bp.on 'destroyed', =>


Fixed max-len lint test

Fixed max-len lint test


Trivial fix :/

Trivial fix :/

--- src/spec.coffee
+++ src/spec.coffee
@@ -264,7 +264,7 @@
                 @field.size = metrics.memory_actual
             }
             VM_guest_metrics: {
-              update: (metrics, UUID)
+              update: (metrics, UUID) ->
                 return if UUID isnt refsToUUIDs[@generator.metrics]

                 @field.size = metrics.memory.total


Don't use snapshots in Task

Don't use snapshots in Task

They are not providing much value, as we are not already loading
anything from the snapshot require cache.

--- src/task.coffee
+++ src/task.coffee
@@ -70,10 +70,6 @@
     compileCachePath = require('./compile-cache').getCacheDirectory()
     taskBootstrapRequire = "require('#{require.resolve('./task-bootstrap')}');"
     bootstrap = """
-      if (typeof snapshotResult !== 'undefined') {
-        snapshotResult.setGlobals(global, process, global, {}, console, require)
-      }
-
       CompileCache = #{compileCacheRequire}
       CompileCache.setCacheDirectory('#{compileCachePath}');
       CompileCache.install("#{process.resourcesPath}", require)


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/text.coffee
+++ src/text.coffee
@@ -9,7 +9,6 @@

   self.bind "update", ->
     I.y -= 1
-    log I.age / I.duration
     I.alpha = 1 - (I.age / I.duration)

   self.unbind "draw"


Fixed bugs with using an old reference of the tree element in reactive updates.

--- src/tree.coffee
+++ src/tree.coffee
@@ -29,7 +29,6 @@
   settings = getSettings()
   template = @
   loadTree(@)
-  $tree = getTreeElement(@)

   # Only a reactive cursor can observe for changes. A simple array can only render a tree once.
   return unless cursor
@@ -48,6 +47,7 @@
           return
         sortResults = getSortedIndex(template, newDoc)
         nextSiblingNode = sortResults.nextSiblingNode
+        $tree = getTreeElement(template)
         if nextSiblingNode
           $tree.tree('addNodeBefore', data, nextSiblingNode)
         else
@@ -69,6 +69,7 @@
         childDocs = model.getChildren(newDoc)
         data.children = _.map childDocs, (childDoc) ->
           getNode(template, childDoc._id)
+        $tree = getTreeElement(template)
         $tree.tree('updateNode', node, data)
         parent = newDoc.parent
         if parent != oldDoc.parent
@@ -86,6 +87,7 @@
         # to be removed.
         return unless node
         removeSelection(template, [id])
+        $tree = getTreeElement(template)
         $tree.tree('removeNode', node)

 TemplateClass.destory = ->
@@ -120,7 +122,23 @@
   treeArgs.onCreateLi = onCreateNode.bind(null, template)
   $tree.tree(treeArgs)

-refreshTree = _.debounce(loadTree, 1000)
+# TODO(aramk) Put into utility.
+debounceLeft = (func, delay) ->
+  isPressed = true
+  handle = null
+  press = ->
+    isPressed = true
+    setTimeout((-> isPressed = false), delay)
+  wrapped = ->
+    if isPressed
+      press()
+      return
+    result = func.apply(null, arguments)
+    press()
+    result
+  wrapped
+
+refreshTree = debounceLeft(loadTree, 1000)

 ####################################################################################################
 # EXPANSION


WIP - ScrollElement is not basically usable. There are a few big things missing: animated over-scroll restor and flicking momentum.

--- source/Art/Engine/Elements/Widgets/ScrollElement.coffee
+++ source/Art/Engine/Elements/Widgets/ScrollElement.coffee
@@ -68,10 +68,13 @@
     oldCurrentPage: element
     currentPage:    element
   scrollUpdate:
-    currentPage:          element           - @currentPage
-    currentGeometry:      plain object      - @currentGeometry
-    pagesBeforeBaseline:  array of elements - @pagesBeforeBaseline
-    pagesAfterBaseline:   array of elements - @pagesAfterBaseline
+    childrenOffset:           number (pixels)
+    childrenSize:             number (pixels)
+    windowSize:               number (pixels)
+    focusedChild:             element
+    firstOnScreenChildIndex:  number
+    lastOnScreenChildIndex:   number
+    focusedChildIndex:        number

 naming:

@@ -92,252 +95,6 @@
     - use pending values only as inputs to computation that results in setting another property
     - use current (non-pending) poperty values for all getters
 ###
-
-
-###
-ScrollAnimator
-
-scrollElement api:
-  @getter
-    minScrollPosition:
-    maxScrollPosition:
-    scrollPosition:
-
-  @setter
-    scrollPosition: (scrollPosition) ->
-
-onIdle is called when all animations and gestures have stopped.
-
-###
-# class ScrollAnimator extends BaseObject
-#   constructor: (@scrollElement, @maximumVelocity)->
-#     super
-#     @_referenceFrame = @scrollElement.getPendingReferenceFrame()
-#     @_velocity = 0
-#     @_mode = "tracking"
-#     ###
-#     modes:
-#       braking:      friction only
-#       spring:       spring
-#       tracking:     direct tracking, no physics
-#     ###
-
-#   @getter "desiredScrollPosition",
-#     mode:               -> @_mode
-#     minScrollPosition:  -> @scrollElement.getMinScrollPositionInReferenceFrame @_referenceFrame
-#     maxScrollPosition:  -> @scrollElement.getMaxScrollPositionInReferenceFrame @_referenceFrame
-#     scrollPosition:     -> @scrollElement.getScrollPositionInReferenceFrame @_referenceFrame
-#     # closestPageLocation: -> @scrollElement.getClosestPageLocation()
-#     animationDone: ->
-#       switch @mode
-#         when "spring"  then @velocityIsSlow() && @_desiredScrollPosition == @getScrollPosition()
-#         when "braking" then @velocityIsSlow()
-#         else !@_activeTouch # && abs(@_velocity) < 1 && l >= @minScrollPosition && l <= @maxScrollPosition
-#     animationContinues: -> !@getAnimationDone()
-#     # shouldSnapToPage: ->
-#     #   abs(@closestPageLocation - @scrollPosition) < @scrollElement.snapToPageDistance
-
-#   @setter "desiredScrollPosition",
-#     mode: (v) -> @_mode = v
-#     referenceFrame: (v) ->
-#       # log "scrollAnimator referenceFrame: #{inspect v}"
-#       @_referenceFrame = v
-#     scrollPosition: (l) -> @scrollElement.setScrollPositionInReferenceFrame round(l), @_referenceFrame
-#     activeTouch: (v) ->
-#       unless @_activeTouch = !!v
-#         @mode = "spring"
-#         @_desiredScrollPosition = @boundLocation @_desiredScrollPosition
-#         # @snapToPage() if @shouldSnapToPage
-
-#   addToDesiredScrollPosition: (delta) ->
-#     @_desiredScrollPosition += delta
-
-#   animateToLocation: (desiredScrollPosition) ->
-#     @mode = "spring"
-#     @_desiredScrollPosition = desiredScrollPosition
-
-#   boundLocation: (scrollPosition) ->
-#     # log "boundedLocation", scrollPosition,
-#     bound @getMinScrollPosition(), scrollPosition, @getMaxScrollPosition()
-
-#   startTracking: (desiredScrollPosition, referenceFrame) ->
-#     @_referenceFrame = referenceFrame
-#     @mode = "tracking"
-#     @_velocity = 0
-#     @setDesiredScrollPosition desiredScrollPosition
-#     @_activeTouch = true
-
-#   addVelocity: (v) ->
-#     @_velocity = v
-#     @mode = "braking"
-
-#   velocityIsSlow: -> absLte @_velocity, 60
-
-#   # returns true if animation continues
-#   frameCount = 0
-#   missCount = 0
-#   frameUpdate: (frameTime) ->
-#     # log frameUpdate:
-#     #   frameTimeFPS: (1 / frameTime) + .5 | 0
-#     #   mode: @_mode
-
-#     # <DEBUG>
-#     tookFrames = Math.round frameTime * 60
-#     frameCount++
-#     if absLt frameTime*60 - 1, .25
-#     else
-#       missCount++ if tookFrames > 1
-#       # log "frameUpdate #{@_mode}: took #{frameTime*60} frames (miss rate: #{missCount} / #{frameCount})"
-#     # </DEBUG>
-
-#     scrollPosition = @getScrollPosition()
-#     targetScrollPosition = @_desiredScrollPosition
-
-#     @_velocity = maxMagnitude @_velocity, @maximumVelocity
-
-#     switch @_mode
-#       when "tracking"
-#         # DIRECT TRACKING (no animation)
-#         {windowSize} = @scrollElement
-#         boundedTargetLocation = @boundLocation targetScrollPosition
-#         maxBeyond = windowSize / 3
-#         minV = min boundedTargetLocation, targetScrollPosition
-#         maxV = max boundedTargetLocation, targetScrollPosition
-#         targetScrollPosition = bound minV,
-#           boundedTargetLocation + Math.atan((targetScrollPosition - boundedTargetLocation) / maxBeyond ) * (2 / Math.PI) * maxBeyond
-#           maxV
-#         @_velocity = 0
-#         @setScrollPosition targetScrollPosition
-
-#       when "braking"
-#         @_activeTouch = false
-#         frictionConstant = brakingFactor
-#         frictionAcceleration = @_velocity * -frictionConstant
-#         acceleration = frictionAcceleration
-#         @_velocity += acceleration * frameTime
-#         scrollPosition = scrollPosition + @_velocity * frameTime
-#         @setScrollPosition scrollPosition
-
-#         if scrollPosition != boundedLocation = @boundLocation scrollPosition
-#           @mode = "spring"
-#           @_desiredScrollPosition = boundedLocation
-
-#         # if abs(@_velocity) < 15 && @shouldSnapToPage
-#         #   @snapToPage()
-
-#       when "spring"
-#         # PHYSICS
-#         currentToTargetVector = targetScrollPosition - scrollPosition
-#         distanceSquared = currentToTargetVector * currentToTargetVector
-
-#         springConstant   = animatorSpringConstant
-#         frictionConstant = animatorSpringFriction
-#         springAcceleration = currentToTargetVector * springConstant
-#         frictionAcceleration = @_velocity * -frictionConstant
-#         acceleration = springAcceleration + frictionAcceleration
-
-#         @_velocity = @_velocity + acceleration * frameTime
-#         @setScrollPosition if @velocityIsSlow() && abs(scrollPosition - targetScrollPosition) <= 1
-#           targetScrollPosition
-#         else
-#           scrollPosition + minMagnitude @_velocity * frameTime, 1
-
-#     # <DEBUG>
-#     unless @getAnimationContinues()
-#       log "frameUpdate #{@_mode}: DONE (miss rate: #{missCount} / #{frameCount})"
-#     # </DEBUG>
-
-#     @getAnimationContinues()
-
-# AnimatorSupport = (superClass) -> class AnimatorSupport extends superClass
-
-#   @getter
-#     animatorsActive: -> !!@_activeAnimators
-
-#   initAnimatorSupport: ->
-#     @_lastTime = 0
-#     @_activeAnimators = null
-#     @_frameUpdateQueued = false
-
-#   # OUT: animator
-#   startAnimator: (animator) ->
-#     if @getAnimatorsActive()
-#       @_activeAnimators.push animator
-#     else
-#       @_activeAnimators = [animator]
-#       @_lastTime = currentSecond()
-#       @getAnimatorsActive()
-
-#     @_startAnimatorLoop()
-#     animator
-
-#   ###
-#   OUT: newAnimator
-#   SIDE-EFFECT:
-#     if oldAnimator is in @_activeAnimators
-#     then: replaced it with newAnimator
-#     else: @startAnimator newAnimator
-
-#   POST ASSERTIONS
-#     newAnimator is in @_activeAnimators
-#     oldAnimator is NOT in @_activeAnimators
-
-#   ###
-#   replaceAnimator: (newAnimator, oldAnimator) ->
-#     return @startAnimator newAnimator unless @_activeAnimators && oldAnimator
-#     index = @_activeAnimators.indexOf oldAnimator
-#     return @startAnimator newAnimator unless index >= 0
-#     @_activeAnimators[index] = newAnimator
-
-#   stopAllAnimators: ->
-#     @_activeAnimators = null
-
-#   _frameUpdate: (frameTime)->
-#     return unless @_activeAnimators
-#     # log "_frameUpdate"
-#     now = frameTime #currentSecond()
-#     frameTime = now - @_lastTime
-
-#     nextAnimators = null
-#     for animator, i in @_activeAnimators
-#       if animator.frameUpdate frameTime
-#         nextAnimators?.push animator
-#       else
-#         # log _frameUpdate: animatorDone: animator
-#         @queueEvent "animatorDone", animator: animator
-#         nextAnimators ||= @_activeAnimators.slice 0, i
-
-#     if nextAnimators
-#       if nextAnimators.length == 0
-#         @_activeAnimators = null
-#         @queueEvent "allAnimatorsDone"
-#       else
-#         @_activeAnimators = nextAnimators
-
-#     @_lastTime = now
-
-#   _startAnimatorLoop: ->
-#     return if @_frameUpdateQueued
-#     requestAnimationFrame (frameTimeMs) =>
-#       @_lastTime = frameTimeMs / 1000
-
-#       queueNextFrameUpdate = =>
-#         # log "_startAnimatorLoop: queueNextFrameUpdate", @_activeAnimators
-#         return unless @getAnimatorsActive()
-#         @_frameUpdateQueued = true
-#         requestAnimationFrame (frameTimeMs) =>
-
-#         # TODO: I want to rework this to use onNextReady
-#         # eventEpoch.onNextReady will help us track time spent preparing the next frame
-#         # BUT, I need to use the frameTimeMs requestAnimationFrame provides - it smooths out the animation.
-#         # ALL animations need to start using it.
-#         #
-#         # eventEpoch.onNextReady =>
-#           @_frameUpdateQueued = false
-#           @_frameUpdate frameTimeMs / 1000
-#           queueNextFrameUpdate()
-
-#       queueNextFrameUpdate()

 defineModule module, class ScrollElement extends Element

@@ -438,14 +195,15 @@

     log "tracking: #{@_pendingState._tracking} #{_scrollPosition}"

-  _updateOnScreenInfo: (inFlowChildren) ->
-    {isVertical, childrenSize, windowSize} = @
+  _updateOnScreenInfo: ->
+    {isVertical, windowSize} = @

     focusedChild = @_pendingState._focusedChild

     children = @_pendingState._children
     firstOnScreenChildIndex = children.length
-    focusedChildIndex = lastOnScreenChildIndex = -1
+    lastOnScreenChildIndex =
+    focusedChildIndex = -1

     for child, i in children
       if child.getPendingInFlow()
@@ -472,7 +230,8 @@
       )
       @queueEvent "scrollUpdate", =>
         {
-          childrenSize
+          @childrenOffset
+          @childrenSize
           windowSize
           focusedChild
           firstOnScreenChildIndex
@@ -505,28 +264,6 @@
     @_pendingState._focusedChild = focusedChild
     focusedChildPos

-  # constructor: ->
-  #   @initAnimatorSupport()
-
-  #   # initializing props before "super" since super triggers "setChildren", which needs these
-  #   @_initGestureProps()
-  #   @_pages = null
-  #   @_currentPage = null
-  #   @_atEnd = false
-  #   @_atStart = true
-  #   @_scrollContents =
-  #   @_pagesBeforeBaselineWrapper =
-  #   @_pagesAfterBaselineWrapper = null
-  #   @_setVerticalAxis()
-  #   @_lastScrollUpdatedAt = currentSecond()
-  #   @_activelyScrolling = false
-  #   super
-  #   self.pagingScrollElement = @
-  #   @_updateHiddenChildren()
-  #   @onNextReady =>
-  #     @jumpToEnd() if @startAtEnd
-  #     @_scrollPositionChanged()
-
   animateToValidScrollPosition: ->
     pendingScrollPosition = @getScrollPosition true

@@ -589,110 +326,6 @@
           move:       @gestureMove.bind @
           end:        @gestureEnd.bind @

-  # _setVerticalAxis: ->
-  #   @newPoint = (mainV, crossV = 0) -> point crossV, mainV
-  #   @getPagePosition = (page) -> page?.transformToAncestorSpaceY(0, @) || 0
-  #   @getMainCoordinate = (pnt) -> pnt.y
-
-  # _setHorizontalAxis: ->
-  #   @newPoint = (mainV, crossV = 0) -> point mainV, crossV
-  #   @getPagePosition = (page) -> page?.transformToAncestorSpaceX(0, @) || 0
-  #   @getMainCoordinate = (pnt) -> pnt.x
-
-  # getPageSize: (page) -> if !page then 0 else @getMainCoordinate page.getCurrentSize()
-  # getPageEdgeOffset: ({page, atEndEdge}) -> if atEndEdge then @getPageSize page else 0
-  # getPageCenter: (page)-> @getPagePosition(page) + @getPageSize(page) / 2
-
-  # defaultReferenceFrame =
-  #   page: null
-  #   atEndEdge: false
-
-  # @concreteProperty
-  #   startAtEnd: default: false
-
-  #   referenceFrame:
-  #     default: defaultReferenceFrame
-
-  #     postSetter: (newReferenceFrame, previousReferenceFrame) ->
-  #       console.warn "referenceFrame_postSetter - frame didn't change" unless newReferenceFrame != previousReferenceFrame
-
-  #       @_addToScrollPosition delta = @getReferenceFrameDelta newReferenceFrame, previousReferenceFrame
-  #       # log setReferenceFrame:
-  #       #   newReferenceFrame: newReferenceFrame
-  #       #   previousReferenceFrame: previousReferenceFrame
-  #       #   delta: delta
-
-  #       @_updatePointerReferenceFrame newReferenceFrame
-
-  #       @_queueUpdateEvent newReferenceFrame, previousReferenceFrame
-
-  #       @_updatePagesSplit()
-
-  #   pages:
-  #     default: []
-  #     validate: (pages) -> isPlainArray pages
-  #     postSetter: (pages, oldPages)->
-
-  #       {page, atEndEdge} = referenceFrame = @getPendingReferenceFrame()
-
-  #       if @_atEnd
-  #         atEndEdge = true
-  #         page = last pages
-  #       if @_atStart || !page
-  #         atEndEdge = false
-  #         page = first pages
-
-  #       # log setPages:
-  #       #   atStart: @_atStart
-  #       #   atEnd: @_atEnd
-  #       #   pages: pages && (p?.inspectedName for p in pages)
-  #       #   referenceFrame:
-  #       #     page: page?.inspectedName
-  #       #     atEndEdge: atEndEdge
-
-  #       if referenceFrame.page && 0 > pages.indexOf referenceFrame.page
-  #         console.warn(
-  #           """
-  #           PagingScrollElement#pages setter: New page list does not contain the current referenceFrame. ALWAYS include the current referenceFrame when setting pages. Screen will jump!
-
-  #           page keys: #{inspect (page.key for page in pages)}
-  #           """
-  #         )
-
-  #       if referenceFrame.page != page || referenceFrame.atEndEdge != atEndEdge
-  #         # setReferenceFrame will call _updatePagesSplit
-  #         @setReferenceFrame page: page, atEndEdge: atEndEdge
-  #       else
-  #         @_updatePagesSplit()
-
-  #       if oldPages.length > 0
-  #         @onNextReady => @_updateAtStartAndAtEnd()
-
-  #   scrollPosition:
-  #     default: 0
-  #     postSetter: (position) ->
-  #       @_scrollPositionChanged()
-  #       # throw new Error if maxCount-- < 0
-  #       # console.error "setScrollPosition #{position}"
-  #       @onNextReady => @_updateAtStartAndAtEnd()
-  #       ###
-  #       TODO
-  #       NOTES on childrenAlignment:
-  #         This doesn't work yet.
-
-  #         This needs to update whenever the size of children or parent changes.
-
-  #         This code only updates when scrollPosition changes.
-  #       ###
-  #       # if @_scrollContents.getCurrentSize().lte @getCurrentSize()
-  #       #   axis = @_scrollContents.setAxis @getPendingChildrenAlignment()
-  #       #   @_scrollContents.setLocation ww: axis.x, hh: axis.y
-  #       #   @newPoint position
-  #       # else
-  #       #   @_scrollContents.setAxis 0
-  #       @_scrollContents.setLocation @newPoint position
-  # # maxCount = 5
-
   _scrollPositionChanged: ->
     unless @_activelyScrolling
       @queueEvent "scrollingActive"
@@ -704,119 +337,6 @@
         @_activelyScrolling = false
         @queueEvent "scrollingIdle"

-  # _updatePagesSplit: (pages = @getPendingPages(), referenceFrame = @getPendingReferenceFrame())->
-
-  #   {page, atEndEdge} = referenceFrame
-
-  #   splitIndex = pages.indexOf page
-  #   if splitIndex < 0
-
-  #     if page
-  #       console.warn "PagingScrollElement#_updatePagesSplit: could not find the old
-  #         referenceFrame.page(key: #{page.key || page.inspectedName}) in the new children. New current page picked;
-  #         display WILL jump."
-
-  #     splitIndex = 0
-
-  #   splitIndex++ if atEndEdge
-
-  #   @_pagesBeforeBaselineWrapper.setChildren pages.slice 0, splitIndex
-  #   @_pagesAfterBaselineWrapper.setChildren  pages.slice splitIndex
-
-  # @layoutProperty
-  #   scroll:
-  #     default: "vertical"
-  #     validate: (v) -> v == "vertical" || v == "horizontal"
-  #     postSetter: (newV, oldValue) ->
-  #       if newV == "vertical"
-  #         @_setVerticalAxis()
-  #       else
-  #         @_setHorizontalAxis()
-  #       @_updateHiddenChildren newV
-
-  # ######################################
-  # # ScrollAnimator expects this API
-  # ######################################
-
-  # getReferenceFrameDelta: (toReferenceFrame = defaultReferenceFrame, fromReferenceFrame = defaultReferenceFrame) ->
-  #   return 0 if toReferenceFrame == fromReferenceFrame
-
-  #   positionDelta = if toReferenceFrame.page == fromReferenceFrame.page then 0
-  #   else @getPagePosition(toReferenceFrame.page) - @getPagePosition(fromReferenceFrame.page)
-
-  #   edgeDelta = @getPageEdgeOffset(toReferenceFrame) - @getPageEdgeOffset fromReferenceFrame
-
-  #   positionDelta + edgeDelta
-
-  # getScrollPositionInReferenceFrame: (targetReferenceFrame) ->
-  #   @getScrollPosition() + @getReferenceFrameDelta targetReferenceFrame, @getReferenceFrame()
-
-  # setScrollPositionInReferenceFrame: (scrollPosition, referenceFrame = @getPendingReferenceFrame()) ->
-  #   @onNextReady => @_updateReferenceFrame()
-
-  #   pendingReferenceFrame = @getPendingReferenceFrame()
-
-  #   scrollPosition        += @getReferenceFrameDelta pendingReferenceFrame, referenceFrame
-
-  #   # TODO: I'd like to do this "boundedScrollPosition", but it messes up ScrollAnimator
-  #   #   I think that means we'd have to have an "actual" scroll position and the scrollPosition
-  #   #   ScrollAnimator sees. Further, if they are out of sync, we need another animator bringing
-  #   #   them into sync as quickly as possible.
-  #   # currentScrollPosition = @getScrollPosition()
-  #   # currentReferenceFrame = @getReferenceFrame()
-  #   # currentScrollPosition += @getReferenceFrameDelta pendingReferenceFrame, currentReferenceFrame
-
-  #   # boundedScrollPosition = maxChange scrollPosition, currentScrollPosition, @getWindowSize() / 2
-  #   # if boundedScrollPosition != scrollPosition
-  #   #   log
-  #   #     boundedScrollPosition: boundedScrollPosition
-  #   #     scrollPosition: scrollPosition
-  #   #     currentScrollPosition: currentScrollPosition
-  #   #     windowSize: @getWindowSize()
-
-  #   # never move more than one screen-full in one frame
-  #   @setScrollPosition scrollPosition
-
-  # @getter
-  #   minScrollPosition: -> @getMinScrollPositionInReferenceFrame @getReferenceFrame()
-  #   maxScrollPosition: -> @getMaxScrollPositionInReferenceFrame @getReferenceFrame()
-
-  # getMinScrollPositionInReferenceFrame: (referenceFrame)->
-  #   windowSize = @getWindowSize()
-  #   beforeSize = @getPagesBeforeBaselineSize()
-  #   afterSize = @getPagesAfterBaselineSize()
-  #   return 0 if beforeSize + afterSize <= windowSize
-  #   windowSize - afterSize + @getReferenceFrameDelta referenceFrame, @getReferenceFrame()
-
-  # getMaxScrollPositionInReferenceFrame: (referenceFrame)->
-  #   windowSize = @getWindowSize()
-  #   beforeSize = @getPagesBeforeBaselineSize()
-  #   afterSize = @getPagesAfterBaselineSize()
-  #   delta = @getReferenceFrameDelta referenceFrame, @getReferenceFrame()
-  #   # log getMaxScrollPositionInReferenceFrame:
-  #   #   referenceFrame: referenceFrame
-  #   #   windowSize:windowSize
-  #   #   beforeSize:beforeSize
-  #   #   afterSize:afterSize
-  #   #   delta:delta
-  #   return 0 if beforeSize + afterSize <= windowSize
-  #   beforeSize + delta
-
-  # jumpToStart: ->
-  #   @setScrollPositionInReferenceFrame 0,
-  #     page: first @getPendingPages()
-  #     atEndEdge: false
-
-  # jumpToEnd: ->
-  #   log "jumpToEnd"
-  #   if @getPagesFitInWindow()
-  #     @jumpToStart()
-  #   else
-  #     @setScrollPositionInReferenceFrame @getWindowSize(),
-  #       page: last @getPendingPages()
-  #       atEndEdge: true
-
-  # ######################################
   @getter
     isVertical:                -> @_childrenLayout == "column"

@@ -835,71 +355,6 @@

       numChildrenOnScreen

-  #   atEnd:                     -> @_atEnd
-  #   atStart:                   -> @_atStart
-  #   inMiddle:                  -> !@_atEnd && !@_atStart
-  #   pagesFitInWindow:          -> @getWindowSize() >= @getTotalPageSize()
-  #   currentPagePosition:       -> @getMainCoordinate @_scrollContents.getCurrentLocation()
-  #   pagesBeforeBaselineSize:   -> @getMainCoordinate @_pagesBeforeBaselineWrapper.getCurrentSize()
-  #   pagesAfterBaselineSize:    -> @getMainCoordinate @_pagesAfterBaselineWrapper.getCurrentSize()
-  #   pagesBeforeBaseline:       -> @_pagesBeforeBaselineWrapper.getChildren()
-  #   pagesAfterBaseline:        -> @_pagesAfterBaselineWrapper.getChildren()
-  #   totalPageSize:             -> @getPagesBeforeBaselineSize() + @getPagesAfterBaselineSize()
-
-  #   # should return 1 + the number of non-focusedPage pages on-screen in _pagesBeforeBaselineWrapper
-  #   pagesOnScreenBeforeBaseline: ->
-  #     pixelsOnScreen = @getScrollPosition()
-  #     totalSize = 0
-  #     count = 0
-  #     for page in pages = @_pagesBeforeBaselineWrapper.getChildren() by -1
-  #       count++
-  #       totalSize += @getMainCoordinate page.getCurrentSize()
-  #       break if totalSize >= pixelsOnScreen
-
-  #     if totalSize < pixelsOnScreen && pages.length > 0 && totalSize > 0
-  #       averagePageSize = totalSize / pages.length
-  #       pixelsLeft = pixelsOnScreen - totalSize
-  #       count += ceil pixelsLeft / averagePageSize
-  #     count
-
-  #   # should return 1 + the number of non-focusedPage pages on-screen in _pagesAfterBaselineWrapper
-  #   pagesOnScreenAfterBaseline: ->
-  #     pixelsOnScreen = @getWindowSize() - @getScrollPosition()
-  #     totalSize = 0
-  #     count = 0
-  #     for page in pages = @_pagesAfterBaselineWrapper.getChildren()
-  #       count++
-  #       totalSize += @getMainCoordinate page.getCurrentSize()
-  #       break if totalSize >= pixelsOnScreen
-
-  #     if totalSize < pixelsOnScreen && pages.length > 0 && totalSize > 0
-  #       averagePageSize = totalSize / pages.length
-  #       pixelsLeft = pixelsOnScreen - totalSize
-  #       count += ceil pixelsLeft / averagePageSize
-  #     count
-
-  #   currentGeometry: ->
-  #     windowSize = @getWindowSize()
-  #     currentPos = @getCurrentPagePosition()
-  #     pixelsBefore = @getPagesBeforeBaselineSize()
-  #     pixelsAfter = @getPagesAfterBaselineSize()
-  #     numPages = @_pages.length
-  #     totalPageSize = pixelsBefore + pixelsAfter
-
-  #     suggestedPageSpread = @getPagesOnScreenBeforeBaseline() + @getPagesOnScreenAfterBaseline()
-
-  #     currentPagePosition:              currentPos
-  #     windowSize:                       windowSize
-  #     numPages:                         numPages
-  #     numPagesBeforeBaseline:           @_pagesBeforeBaselineWrapper.getChildren().length
-  #     numPagesAfterBaseline:            @_pagesAfterBaselineWrapper.getChildren().length
-  #     totalPageSize:                    totalPageSize
-  #     focusedPageBeforeBaseline:        @getReferenceFrame().atEndEdge
-  #     suggestedPageSpread:              suggestedPageSpread
-  #     pixelsOffscreenBeforeWindow:      pixelsBefore - currentPos
-  #     pixelsOffscreenAfterWindow:       pixelsAfter - windowSize + currentPos
-  #     pagesBeforeBaselineSize:          pixelsBefore
-  #     pagesAfterBaselineSize:           pixelsAfter

   # ###################
   # # Gestures
@@ -993,166 +448,3 @@
     #   @_flicked = true
     # else
     #   @endScrollAnimatorTracking()
-
-  # startScrollAnimatorTracking: ->
-  #   @getScrollAnimator().startTracking @_scrollPosition, @_referenceFrame
-
-  # endScrollAnimatorTracking: ->
-  #   return unless scrollAnimator = @getActiveScrollAnimator()
-  #   scrollAnimator.setReferenceFrame @getReferenceFrame()
-  #   scrollAnimator.setDesiredScrollPosition @getScrollPosition()
-  #   scrollAnimator.setActiveTouch false
-
-
-  # #####################
-  # # PRIVATE
-  # #####################
-
-  # ###
-  # When children are set "from outside", we split them based on the @_currentPage and set then as
-  # grandchildren - children of the direct, but hidden children:
-  #   _pagesBeforeBaselineWrapper or
-  #   _pagesAfterBaselineWrapper
-
-  # Why? This allows us to leverage existing row and column layouts to do most of
-  # the heavy lifting for actual element layout.
-  # ###
-  # setChildren: (newPages, oldChildren = @getPendingChildren()) ->
-  #   newChildren = unless oldChildren?.length > 0
-  #     @_updateHiddenChildren()
-  #     [@_scrollContents]
-  #   else
-  #     oldChildren
-
-  #   @setPages newPages
-  #   super newChildren
-
-  # _updatePointerReferenceFrame: (newReferenceFrame) ->
-  #   return unless @_pointerReferenceFrame
-  #   delta = @getReferenceFrameDelta newReferenceFrame, @_pointerReferenceFrame
-  #   @_pointerStartPosition -= delta
-  #   @getActiveScrollAnimator()?.addToDesiredScrollPosition delta
-  #   @getActiveScrollAnimator()?.setReferenceFrame @_pointerReferenceFrame = newReferenceFrame
-
-  # _getPageUnderPosition: (testPosition)->
-  #   relativeTestPosition = testPosition - @getScrollPosition()
-  #   wrapper = if relativeTestPosition < 0
-  #     relativeTestPosition += @getMainCoordinate @_pagesBeforeBaselineWrapper.getCurrentSize()
-  #     @_pagesBeforeBaselineWrapper
-  #   else
-  #     @_pagesAfterBaselineWrapper
-
-  #   # log _getPageUnderPosition:
-  #   #   beforeBaseline: wrapper == @_pagesBeforeBaselineWrapper
-  #   #   testPosition: testPosition
-  #   #   relativeTestPosition: relativeTestPosition
-  #   #   sizes: ("#{child.key}: #{@getMainCoordinate child.getCurrentSize()}" for child in wrapper.getChildren())
-
-  #   for child in wrapper.getChildren()
-  #     size = @getMainCoordinate child.getCurrentSize()
-  #     return child if relativeTestPosition < size
-  #     relativeTestPosition -= size
-
-  #   console.warn "PagingScrollElement#_getPageUnderPosition: could not find page under position"
-  #   null
-
-  # # _getPageUnderLocation: (scrollPosition)->
-  # #   scrollPosition = @_scrollContents.getParentToElementMatrix().transform scrollPosition
-  # #   if elementGroup = @_scrollContents.childUnderPoint scrollPosition
-  # #     scrollPosition = elementGroup.getParentToElementMatrix().transform scrollPosition
-  # #     elementGroup.childUnderPoint scrollPosition
-
-  # # returns true if at start or end
-  # _updateAtStartAndAtEnd: ->
-  #   scrollPosition = @getScrollPosition()
-  #   if @getTotalPageSize() <= @getWindowSize()
-  #     # TODO: support preferAtEnd
-  #     newAtStart = true
-  #     newAtEnd = false
-  #   else
-  #     newAtEnd   = scrollPosition <= @getMinScrollPosition()
-  #     newAtStart = scrollPosition >= @getMaxScrollPosition()
-
-  #   pages = @getPages()
-
-  #   if newAtStart && newAtStart != @_atStart
-  #     # log "_updateAtStartAndAtEnd setReferenceFrame atStart #{scrollPosition} >= #{@getMaxScrollPosition()}"
-  #     @setReferenceFrame page: first pages
-  #   else if newAtEnd && newAtEnd != @_atEnd
-  #     # log "_updateAtStartAndAtEnd setReferenceFrame atEnd #{scrollPosition} <= #{@getMinScrollPosition()}"
-  #     @setReferenceFrame atEndEdge: true, page: last pages
-
-  #   @_atEnd = newAtEnd
-  #   @_atStart = newAtStart
-
-  #   # log _updateAtStartAndAtEnd:
-  #   #   scrollPosition: scrollPosition
-  #   #   minSP: @getMinScrollPosition()
-  #   #   maxSP: @getMaxScrollPosition()
-  #   #   atStart: @_atStart
-  #   #   atEnd: @_atEnd
-
-  #   newAtEnd || newAtStart
-
-  # _addToScrollPosition: (delta) ->
-  #   @setScrollPosition @getPendingScrollPosition() + delta
-
-  # ###
-  # update currentPage to be the page that overlaps the center-line of the view-window
-
-  # need to:
-  #   update scrollPosition
-  #   need to @_setChildren
-
-  # ###
-  # _updateReferenceFrame: ->
-  #   return if @_updateAtStartAndAtEnd()
-
-  #   scrollPosition = @getScrollPosition()
-
-  #   centerPosition = @getWindowSize() / 2
-  #   newCurrentPage = @_getPageUnderPosition centerPosition
-  #   console.warn "_updateReferenceFrame: no newCurrentPage" unless newCurrentPage
-  #   pageCenterPosition = @getPageCenter newCurrentPage
-
-  #   # log _updateReferenceFrame:
-  #   #   center: center
-  #   #   newCurrentPage: newCurrentPage
-  #   #   pageCenterPosition: pageCenterPosition
-  #   #   centerPosition: centerPosition
-
-  #   atEndEdge = centerPosition > pageCenterPosition
-
-  #   referenceFrame = @getReferenceFrame()
-
-  #   if referenceFrame.page != newCurrentPage || referenceFrame.atEndEdge != atEndEdge
-  #     @setReferenceFrame page: newCurrentPage, atEndEdge: atEndEdge
-
-  # _sizeChanged: (newSize, oldSize) ->
-  #   @_queueUpdateEvent()
-  #   super
-
-  # _updateHiddenChildren: (scrollMode = @getPendingScroll()) ->
-  #   @_scrollContents ||= new Element
-  #     key: "scrollContents"
-  #     receivePointerEvents: "passToChildren"
-  #     @_pagesBeforeBaselineWrapper = new Element key:"pagesBeforeBaseline"
-  #     @_pagesAfterBaselineWrapper  = new Element key:"pagesAfterBaseline"
-
-  #   if scrollMode == "horizontal"
-  #     commonSizeLayout = hh:1, wcw:1
-  #     @_pagesBeforeBaselineWrapper.setAxis "topRight"
-  #     @_pagesBeforeBaselineWrapper.setChildrenLayout "row"
-  #     @_pagesAfterBaselineWrapper.setChildrenLayout "row"
-  #   else
-  #     commonSizeLayout = ww:1, hch:1
-  #     @_pagesBeforeBaselineWrapper.setAxis "bottomLeft"
-  #     @_pagesBeforeBaselineWrapper.setChildrenLayout "column"
-  #     @_pagesAfterBaselineWrapper.setChildrenLayout "column"
-
-  #   @_scrollContents.setSize commonSizeLayout
-  #   @_pagesBeforeBaselineWrapper.setSize commonSizeLayout
-  #   @_pagesAfterBaselineWrapper.setSize commonSizeLayout
-
-  #   @_lastScrollUpdatedAt = currentSecond()
-  #   @_activelyScrolling = false


Move subject to instance.

Move subject to instance.

--- spec/javascripts/application/seeds_store_spec.js.coffee
+++ spec/javascripts/application/seeds_store_spec.js.coffee
@@ -1,16 +1,15 @@
 describe 'PodsList', ->
-  subject = null
   beforeEach (done) ->
-    subject = new SeedsStore('test')
-    expect(subject.clear()).eventually.notify(done)
+    @subject = new SeedsStore('test')
+    expect(@subject.clear()).eventually.notify(done)
   it 'counts 0', (done) ->
-    expect(subject.countForAll()).eventually.equal(0).notify(done)
+    expect(@subject.countForAll()).eventually.equal(0).notify(done)
   it 'counts n', (done) ->
-    subject.update([{name: 1},{name: 2},{name: 3}])
-    expect(subject.countForAll()).eventually.equal(3).notify(done)
+    @subject.update([{name: 1},{name: 2},{name: 3}])
+    expect(@subject.countForAll()).eventually.equal(3).notify(done)
   it 'readPod', (done) ->
-    subject.update([{name: 1}, {name: 2}])
-    expect(subject.readPod(1)).eventually.eql([{name: 1}]).notify(done)
+    @subject.update([{name: 1}, {name: 2}])
+    expect(@subject.readPod(1)).eventually.eql([{name: 1}]).notify(done)
   describe 'readsFromAll', ->
     listByName = ->
       [
@@ -42,7 +41,7 @@
         list[3]
       ]
     beforeEach (done) ->
-      expect(subject.update(listByName()))
+      expect(@subject.update(listByName()))
         .eventually.notify(done)
     describe 'name', ->
       sortBy = 'name'
@@ -50,25 +49,25 @@
         list = listByName()
         sortOrderAsc = true
         it 'from the beginning', (done) ->
-          expect(subject.readFromAll(sortBy, sortOrderAsc, 0, 1)).eventually
+          expect(@subject.readFromAll(sortBy, sortOrderAsc, 0, 1)).eventually
             .eql([list[0]]).notify(done)
         it 'in the middle', (done) ->
-          expect(subject.readFromAll(sortBy, sortOrderAsc, 1, 2)).eventually
+          expect(@subject.readFromAll(sortBy, sortOrderAsc, 1, 2)).eventually
             .eql([list[1], list[2]]).notify(done)
         it 'beyond scope', (done) ->
-          expect(subject.readFromAll(sortBy, sortOrderAsc, 5, 2)).eventually
+          expect(@subject.readFromAll(sortBy, sortOrderAsc, 5, 2)).eventually
             .eql([list[5]]).notify(done)
       describe 'desc', ->
         list = listByName().reverse()
         sortOrderAsc = false
         it 'from the beginning', (done) ->
-          expect(subject.readFromAll(sortBy, sortOrderAsc, 0, 1)).eventually
+          expect(@subject.readFromAll(sortBy, sortOrderAsc, 0, 1)).eventually
             .eql([list[0]]).notify(done)
         it 'in the middle', (done) ->
-          expect(subject.readFromAll(sortBy, sortOrderAsc, 1, 2)).eventually
+          expect(@subject.readFromAll(sortBy, sortOrderAsc, 1, 2)).eventually
             .eql([list[1], list[2]]).notify(done)
         it 'beyond scope', (done) ->
-          expect(subject.readFromAll(sortBy, sortOrderAsc, 5, 2)).eventually
+          expect(@subject.readFromAll(sortBy, sortOrderAsc, 5, 2)).eventually
             .eql([list[5]]).notify(done)
     describe 'stars', ->
       sortBy = 'stars'
@@ -76,24 +75,24 @@
         list = listByStars()
         sortOrderAsc = true
         it 'from the beginning', (done) ->
-          expect(subject.readFromAll(sortBy, sortOrderAsc, 0, 1)).eventually
+          expect(@subject.readFromAll(sortBy, sortOrderAsc, 0, 1)).eventually
             .eql([list[0]]).notify(done)
         it 'in the middle', (done) ->
-          expect(subject.readFromAll(sortBy, sortOrderAsc, 1, 2)).eventually
+          expect(@subject.readFromAll(sortBy, sortOrderAsc, 1, 2)).eventually
             .eql([list[1], list[2]]).notify(done)
         it 'beyond scope', (done) ->
-          expect(subject.readFromAll(sortBy, sortOrderAsc, 5, 2)).eventually
+          expect(@subject.readFromAll(sortBy, sortOrderAsc, 5, 2)).eventually
             .eql([list[5]]).notify(done)
       describe 'desc', ->
         list = listByStars().reverse()
         sortOrderAsc = false
         it 'from the beginning', (done) ->
-          expect(subject.readFromAll(sortBy, sortOrderAsc, 0, 1)).eventually
+          expect(@subject.readFromAll(sortBy, sortOrderAsc, 0, 1)).eventually
             .eql([list[0]]).notify(done)
         it 'in the middle', (done) ->
-          expect(subject.readFromAll(sortBy, sortOrderAsc, 1, 2)).eventually
+          expect(@subject.readFromAll(sortBy, sortOrderAsc, 1, 2)).eventually
             .eql([list[1], list[2]]).notify(done)
         it 'beyond scope', (done) ->
-          expect(subject.readFromAll(sortBy, sortOrderAsc, 5, 2)).eventually
+          expect(@subject.readFromAll(sortBy, sortOrderAsc, 5, 2)).eventually
             .eql([list[5]]).notify(done)


Fix \e width/aperture

Fix \e width/aperture

--- src/glyphs/lowercases/e.coffee
+++ src/glyphs/lowercases/e.coffee
@@ -5,6 +5,7 @@
 	parameters:
 		spacingLeft: 50 * spacing + (31)
 		spacingRight: 30 * spacing
+		anglePen: Math.max( - 10, - 60 * aperture + 81 ) # 21
 	tags: [
 		'all',
 		'latin',
@@ -16,22 +17,15 @@
 			closed: false
 			nodes:
 				0:
-					# x: contours[0].nodes[2].expandedTo[0].x + 245 + (25)
 					x: spacingLeft + ( 240 * width + 188 - 50 ) - (9)
-					y: 190 - (15)
-					dirOut: - 109 + 'deg'
+					y: Math.min( contours[0].nodes[2].y - ( 30 / 520 ) * xHeight, 130 * aperture + 60 ) - (15) # 190 - (15)
+					dirOut: Math.min(
+						- anglePen + 90 + 6 + correctWidthAperture,
+						90
+					) + 'deg'
 					expand: Object({
 						width: ( 115 / 115) * thickness
-						angle: - 21 + 'deg'
-						distr: 0.25
-					})
-				0:
-					x: spacingLeft + ( 240 * width + 188 - 50 ) - (9)
-					y: Math.min( contours[0].nodes[2].y - ( 30 / 520 ) * xHeight, 150 * aperture + 40 ) - (15) # 190 - (15)
-					dirOut: contours[0].nodes[0].expand.angle + Math.PI / 2
-					expand: Object({
-						width: ( 115 / 115) * thickness
-						angle: - Math.max( - 10, - 60 * aperture + 81 ) + 'deg' # 21 + 'deg'
+						angle: - anglePen + 'deg'
 						distr: 0.25
 					})
 				1:


Preserve accordion state

Preserve accordion state

--- src/gui/tabs/info/index.coffee
+++ src/gui/tabs/info/index.coffee
@@ -33,14 +33,18 @@
   ask.$ pane, upgrade, values(up).concat false

   # Start accordions
-  for z in $ 'input', pane
-    z.onclick = ->
-      z = self = @
-      z = z.parentElement until 'TBODY' == z.tagName
-      z.nextSibling.className = if self.checked then '' else 'hide'
+  for z, i in $ 'input', pane
+    z.onclick = do (i)-> ->
+      el = cb = @
+      el = el.parentElement until 'TBODY' == el.tagName
+      el.nextSibling.className = if accordionState[i] = !cb.checked then 'hide' else ''
       self.blur()
+      return
+    if accordionState[i]
+      z.click()
+  return

-  return
+accordionState = []

 values = (rec)->
   for k, v of rec


resurrection.activity: define ActivityInputView::setContent method

--- client/Social/Activity/views/inputview.coffee
+++ client/Social/Activity/views/inputview.coffee
@@ -30,3 +30,23 @@
     tokenViewClass = SuggestedTokenView  if item.data.$suggest
     super item, tokenViewClass

+  setContent: (content, activity) ->
+    tags = {}
+    activity?.tags?.forEach (tag) -> tags[tag.getId()] = tag
+    content = content.replace /\|(.*?):(.*?):(.*?)\|/g, (match, prefix, constructorName, id) =>
+      switch prefix
+        when "#"
+          itemClass = TagLinkView
+          type      = "tag"
+          pistachio = "#{prefix}{{#(title)}}"
+          data      = tags[id]
+
+      tokenView = new TokenView {itemClass, prefix, type, pistachio}, data
+      tokenKey  = "#{tokenView.getId()}-#{tokenView.getKey()}"
+      @tokenViews[tokenKey] = tokenView
+
+      tokenView.setAttributes "data-key": tokenKey
+      tokenView.emit "viewAppended"
+      return tokenView.getElement().outerHTML
+
+    super content


Add spec for creating reversed markers

Add spec for creating reversed markers

--- spec/marker-spec.coffee
+++ spec/marker-spec.coffee
@@ -18,6 +18,14 @@
         expect(marker.hasTail()).toBe true
         expect(markerCreations).toEqual [marker]

+      it "allows a reversed marker to be created", ->
+        marker = buffer.markRange([[0, 3], [0, 6]], isReversed: true)
+        expect(marker.getRange()).toEqual [[0, 3], [0, 6]]
+        expect(marker.getHeadPosition()).toEqual [0, 3]
+        expect(marker.getTailPosition()).toEqual [0, 6]
+        expect(marker.isReversed()).toBe true
+        expect(marker.hasTail()).toBe true
+
       it "allows an invalidation strategy to be assigned", ->
         marker = buffer.markRange([[0, 3], [0, 6]], invalidate: 'inside')
         expect(marker.getInvalidationStrategy()).toBe 'inside'


Fixed leaving game bug

Fixed leaving game bug

--- client/src/nowListener.coffee
+++ client/src/nowListener.coffee
@@ -117,7 +117,7 @@

 now.receivePlayerDisconnect = (playerId) ->
   console.log "Player Disconnected"
-  if not (ScreenSystem.currentScreen instanceof EndOfGameScreen)
+  if not (ScreenSystem.currentScreen instanceof EndGameScreen)
     if(playerId == Game.myPlayerId)
       window.location.reload()
     else


Clean up variabledeclarator builder.

Clean up variabledeclarator builder.

--- js2coffee.coffee
+++ js2coffee.coffee
@@ -932,9 +932,7 @@
     delimit(declarators, @indent())

   VariableDeclarator: (node) ->
-    init = @walk(node.init)
-    init = [ init, "\n" ] unless (/\n$/).test(init.toString())
-    [ @walk(node.id), ' = ', init ]
+    [ @walk(node.id), ' = ', newline(@walk(node.init)) ]

   FunctionExpression: (node, ctx) ->
     params = @makeParams(node.params)


update tests

update tests

--- tests/test.coffee
+++ tests/test.coffee
@@ -3,5 +3,5 @@

 describe "Addition", ->
   it "equals 4", ->
-    result = 2 + 2
+    result = 3 + 1
     result.should.equal(4)


Use isReverse instead of reverse in RegexAddress

--- src/extensions/command-interpreter/regex-address.coffee
+++ src/extensions/command-interpreter/regex-address.coffee
@@ -6,25 +6,25 @@
   regex: null
   reverse: null

-  constructor: (pattern, reverse) ->
-    @reverse = reverse
+  constructor: (pattern, isReversed) ->
+    @isReversed = isReversed
     @regex = new RegExp(pattern)

   getRange: (editor, currentRange) ->
     rangeBefore = new Range([0, 0], currentRange.start)
     rangeAfter = new Range(currentRange.end, editor.getEofPosition())

-    rangeToSearch = if @reverse then rangeBefore else rangeAfter
+    rangeToSearch = if @isReversed then rangeBefore else rangeAfter

     rangeToReturn = null
-    scanMethodName = if @reverse then "backwardsScanInRange" else "scanInRange"
+    scanMethodName = if @isReversed then "backwardsScanInRange" else "scanInRange"
     editor[scanMethodName] @regex, rangeToSearch, (match, range) ->
       rangeToReturn = range

     if rangeToReturn
       rangeToReturn
     else
-      rangeToSearch = if @reverse then rangeAfter else rangeBefore
+      rangeToSearch = if @isReversed then rangeAfter else rangeBefore
       editor[scanMethodName] @regex, rangeToSearch, (match, range) ->
         rangeToReturn = range


Include U+FFFD when checking for binary Pic files

This is the Unicode "replacement character"; a question mark silhouetted
by a black diamond, familiar to anybody who's ever opened an incorrectly
encoded webpage.

--- grammars/pic.cson
+++ grammars/pic.cson
@@ -59,7 +59,7 @@
 	# Lookahead to avoid highlighting binary .PIC files
 	binary:
 		name: "raw.binary.data"
-		begin: "^(?=.*[\\x00-\\x06])"
+		begin: "^(?=.*[\\x00-\\x06\\uFFFD])"
 		end: "(?=A)B"


Made the labels disappear

Made the labels disappear

--- js/functions.coffee
+++ js/functions.coffee
@@ -15,11 +15,12 @@
       label = poi.name
       startHeight = count * windowHeight
       endHeight = startHeight + windowHeight
-      heights = {startHeight:startHeight, endHeight:endHeight}
+      disappearHeight = endHeight + 200
+      heights = {startHeight:startHeight, endHeight:endHeight, disappearHeight: disappearHeight}

       innerDiv = _.template("

<%= label %>

",{label: label})

-      outerDivData = _.template("data-<%=startHeight%>=\"opacity:0\" data-<%= endHeight %>=\"opacity:1\"",heights)
+      outerDivData = _.template("data-<%=startHeight%>=\"opacity:0\" data-<%= endHeight %>=\"opacity:1\" data-<%= disappearHeight %>=\"opacity:0\"",heights)
       html = _.template("<div class=\"poi\" <%=outerDivData%> ><%= innerDiv %>
",{innerDiv: innerDiv, outerDivData:outerDivData})
       element.append(html);
       count += 1


payment: use payment method info to decide instead of implicit checks

--- client/Main/payment/form.coffee
+++ client/Main/payment/form.coffee
@@ -129,7 +129,7 @@
     { FREE }   = PaymentWorkflow.planTitle
     { MONTH }  = PaymentWorkflow.planInterval
     { KODING } = PaymentWorkflow.provider
-    { currentPlan, planTitle, planInterval, provider } = @state
+    { currentPlan, planTitle, planInterval, provider, paymentMethod } = @state

     operation = PaymentWorkflow.getOperation currentPlan, planTitle

@@ -143,15 +143,11 @@
       @existingCreditCardMessage.hide()
       @yearPriceMessage.hide()

-    # if their currentPlan is not free it means that
-    # we already have their credit card,
-    # don't show existing cc message, show
-    # cc form.
-    if currentPlan is FREE
+    if paymentMethod
+      @submitButton.enable()
+    else
       @form.show()
       @existingCreditCardMessage.hide()
-    else
-      @submitButton.enable()

     @paypalForm.destroy()  unless provider is KODING


enh: derotate to make shift strictly vertical

--- src/animator.coffee
+++ src/animator.coffee
@@ -82,6 +82,21 @@
     #@endOffset * Mdelta * @startOffset^-1 = t1^-1 * t2 * t1
     @endOffset = M.mul t1, @endOffset
     @startOffset = M.mul t1, @startOffset
+
+    #and now apply similarity rotation to both of the start and end points so that t2 is strictly vertical
+    [dx,dy,_] = M.mulv t2, [0,0,1]
+    r = Math.sqrt(dx**2+dy**2)
+
+    if r > 1e-6
+      s = -dy/r
+      c = dx/r
+      R = [c,   s,   0.0,
+           -s,  c,   0.0,
+           0.0, 0.0, 1.0]
+      R = M.mul R, M.rotationMatrix(-Math.PI/2)
+      @endOffset = M.mul R, @endOffset
+      @startOffset = M.mul R, @startOffset
+
     alert "Derotated OK!"

   _setCanvasSize: ->


Fix style a bit.

Fix style a bit.

--- client/helpers/envelopes.coffee
+++ client/helpers/envelopes.coffee
@@ -51,7 +51,7 @@
     if not virtualAccountId or not rate
       showNavError "Please pick an account and enter a rate."
     else
-      Envelopes.update envelopeId, {
+      Envelopes.update(envelopeId, {
         $set: {
           virtualAccountId: virtualAccountId
           rate: rate
@@ -66,6 +66,7 @@
         else
           showNavError "There was a problem updating the envelope. Please try again. If the problem persists, contact us."
           console.log error
+      )
   'click .cancel-editing': (event) ->
     event.preventDefault()
     Session.set 'editingEnvelope', null


Update panel reference with new view.

Update panel reference with new view.

--- client/ide/AppController.coffee
+++ client/ide/AppController.coffee
@@ -59,6 +59,7 @@

     splitView.once 'viewAppended', ->
       splitView.panels.first.attach ideView
+      splitView.panels[0] = ideView.parent
       splitView.options.views[0] = ideView

     ideParent.addSubView splitView


Collaboration: Check existence of participant snapshot map

--- client/ide/AppController.coffee
+++ client/ide/AppController.coffee
@@ -850,6 +850,8 @@

       changes.push change

+    return  unless map
+
     switch change.type

       when 'NewPaneCreated'


updated deprecated methods

updated deprecated methods

--- lib/build.coffee
+++ lib/build.coffee
@@ -5,7 +5,7 @@
 BuildView = require './build-view'

 module.exports =
-  configDefaults:
+  config:
     environment: "",
     arguments: ""


Forgot this

Forgot this

--- SingularityUI/app/lib/router.coffee
+++ SingularityUI/app/lib/router.coffee
@@ -11,7 +11,6 @@
 TasksView = require 'views/tasks'

 TaskView = require 'views/task'
-FilesView = require 'views/files'
 TailView = require 'views/tail'

 RacksView = require 'views/racks'


namespaced unbind

namespaced unbind

--- src/bindable.coffee
+++ src/bindable.coffee
@@ -85,6 +85,7 @@
       if namespace
         eventCallbacks[event] = eventCallbacks.select (callback) ->
           !callback.__PIXIE?[namespace]?
+
       else
         if callback
           eventCallbacks[event].remove(callback)


remove parts of dealing with connection loss exception

--- src/module/zk/zk_client.coffee
+++ src/module/zk/zk_client.coffee
@@ -54,6 +54,7 @@
 		@_client.on("authenticationFailed", ()->
 			Log.info("ZKClient receive event:authenticationFailed")
 		)
+		@_client.ont("")

 	exists : (path, val, cb)->
 		@_client.exists(path, null, -1, cb)
@@ -157,8 +158,6 @@
 						if err.getCode() == ZK.Exception.NO_NODE
 							Log.error("NO_NODE found for path: #{path}")
 							return
-						else if err.getCode() == ZK.Exception.CONNECTION_LOSS
-							@_client.connect()
 						if cb
 							return cb(err, null, null)
 						else
@@ -185,8 +184,6 @@
 						if err.getCode() == ZK.Exception.NO_NODE
 							Log.error("NO_NODE found for path: #{path}")
 							return
-						else if err.getCode() == ZK.Exception.CONNECTION_LOSS
-							@_client.connect()
 						if cb
 							return cb(err, null, null)
 						else


remove path.resolve

remove path.resolve

--- lib/index.coffee
+++ lib/index.coffee
@@ -69,7 +69,7 @@
      ###

     file = (key, obj) ->
-      f = fs.readFileSync path.resolve(obj.file), 'utf8'
+      f = fs.readFileSync obj.file, 'utf8'
       respond.call(@, key, obj, JSON.parse(f))

     ###*


fix done callback option and emit done when recurse=false

--- lib/index.coffee
+++ lib/index.coffee
@@ -12,7 +12,9 @@
     done ?= options.done ? (if 'function' is typeof options then options)

     # when there's a `done` callback, add it and change processing to async
-    if done? then @on 'done', done ; @async = true
+    if done?
+      @on 'done', done
+      @async = true

     # add the each callbacks, when specfied. add the type to `only`
     for event in ['file', 'dir', 'path']
@@ -123,6 +125,7 @@
         results.rejected.strings += result.rejected.strings
         # now call this again if @recurse
         if @recurse then @_iterate dirArray, dirArray.options
+        else @emit 'done', undefined, results

     if 'files' in @only
       action.tempFiles = []


temporarily disable since I believe its can be achieved wish css.

--- lib/input.coffee
+++ lib/input.coffee
@@ -31,20 +31,20 @@
     start = editor.getCursorBufferPosition()
     end = start.translate([0, 1])

-    @marker = editor.markBufferRange Range(start, end),
-      invalidate: 'never'
-      persistent: false
+    # @marker = editor.markBufferRange Range(start, end),
+    #   invalidate: 'never'
+    #   persistent: false
+    #
+    # klass = if @vimState.mode is 'insert' then 'insert' else 'normal'

-    klass = if @vimState.mode is 'insert' then 'insert' else 'normal'
-
-    editor.decorateMarker @marker,
-      type: 'highlight'
-      class: "vim-mode-cursor-#{klass}"
+    # editor.decorateMarker @marker,
+    #   type: 'highlight'
+    #   class: "vim-mode-cursor-#{klass}"

     @view.focus()

   unfocus: ->
-    @marker?.destroy()
+    # @marker?.destroy()
     @subscriptions?.dispose()
     @subscriptions = null


Some fixes to last merge

Some fixes to last merge

--- app/locale/es-419.coffee
+++ app/locale/es-419.coffee
@@ -580,8 +580,8 @@
     intro_1: "CodeCombat es un juego online que enseña a programar.Los estudiantes escriben código en idiomas de programación real."
     intro_2: "No se necesita experiencia previa!"
     free_title: "¿Cuanto cuesta?"
+    cost_china: "CodeCombat es gratis en China por los primeros cinco niveles, despues cuesta $9.99(dólares) por mes para tener acceso a 120+ niveles que son exclusivos en nuestros servidores en China."
     free_1: "CodeCombat Basic es GRATIS! Hay 70+ niveles gratis que cubren cada concepto."
-    cost_china: "CodeCombat es gratis en China por los primeros cinco niveles, despues cuesta $9.99(dólares) por mes para tener acceso a 120+ niveles que son exclusivos en nuestros servidores en China."
     free_2: "Una suscripción mensual le da acceso a tutoriales en vídeo y niveles extra para practicar."
     teacher_subs_title: "¡Los amestros obtienen subscripciones gratuitas!"
     teacher_subs_1: "Por favor contacte"
@@ -599,7 +599,7 @@
     material_title: "Cuánto material hay?"
     material_china: "Aproximadamente 22 horas de juego repartidas en más de 120 niveles sólo para suscriptores, con cinco nueveos niveles cada semana."
     material_1: "Aproximadamente 8 horas de contenido gratis y un adicional de 14 horas de contenido de suscriptores, con cinco nueveos niveles cada semana."
-    concepts_title: "What concepts are covered?"
+#    concepts_title: "What concepts are covered?"
     how_much_title: "¿Cuánto cuesta una subscripción mensual?"
     how_much_1: "una"
     how_much_2: "suscribción mensual"


Get stats of a champion

Get stats of a champion

Signed-off-by: Ian Macalinao <08370e385f4778cad8fe504ec5445edd3d45bd9a@gmail.com>

--- src/champion.coffee
+++ src/champion.coffee
@@ -10,6 +10,25 @@

     @skills = params.skills

+  ##
+  # Gets the stats of the champion at a given level
+  # without items, masteries, runes, etc.
+  #
+  getVanillaStats: (level) ->
+    stats = {}
+
+    for stat in lol.stats.names
+      stats[stat] = (@baseStats[stat] || 0) + (level - 1) * (@statsPerLevel[stat] || 0)
+
+    return stats
+
+  ##
+  # Gets the stats of the champion at a given level
+  # with the given items, masteries, and runes.
+  #
+  getStats: (level, items, masteries, runes) ->
+    return lol.stats.combine [@getItemlessStats(level), lol.stats.combine(items), lol.stats.combine(masteries), lol.stats.combine(runes)]
+
 lol.champions.list = {}
 lol._defChamp = (name, params) ->
   lol.champions.list[name] = new LoLChampion name, params


Issue #46: Don't store alert when skipping


signature xpath fix

signature xpath fix

--- lib/saml2.coffee
+++ lib/saml2.coffee
@@ -160,7 +160,7 @@
 check_saml_signature = (xml, certificate, cb) ->
   doc = (new xmldom.DOMParser()).parseFromString(xml)

-  signature = xmlcrypto.xpath(doc, "/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")
+  signature = xmlcrypto.xpath(doc, ".//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")
   return false unless signature.length is 1
   sig = new xmlcrypto.SignedXml()
   sig.keyInfoProvider = getKey: -> format_pem(certificate, 'CERTIFICATE')


Fix preventing App.run from requires.

Fix preventing App.run from requires.

--- src/batman.coffee
+++ src/batman.coffee
@@ -1248,7 +1248,7 @@
           success: (response) =>
             CoffeeScript.eval response
             @allow 'run'
-            @fire 'run' if @hasRun
+            @run() if @wantsToRun
       @

   @controller: (names...) ->
@@ -1277,6 +1277,13 @@
       Batman.currentApp.stop()

     return false if @hasRun
+
+    if @isPrevented 'run'
+      @wantsToRun = true
+      return false
+    else
+      delete @wantsToRun
+
     Batman.currentApp = @

     if typeof @dispatcher is 'undefined'


Tracking out site clicks.

Tracking out site clicks.

--- lib/track.coffee
+++ lib/track.coffee
@@ -5,9 +5,24 @@
 imgbin = new Buffer "47494638396101000100800000dbdfef00000021f" +
   "90401000000002c00000000010001000002024401003b", 'hex'

-jsContent = "document.write('');"
+jsContent = """
+
+document.write('');
+
+window.onload = function() {
+   var all = document.getElementsByTagName('a');
+   for (var i=0; i<all.length;i++) {
+      all[i].onclick = _aClickHandler;
+  }
+}
+
+function _aClickHandler(e) {
+   e= e||window.event;
+   var trgSrc = e.target||e.srcElement;
+   document.body.insertAdjacentHTML('beforeEnd','');
+}
+
+"""

 genLog = (req) ->
   ip = req.header('x-forwarded-for') || req.connection.remoteAddress
@@ -36,6 +51,8 @@
 exports.index = (req, res) ->
   res.send """

+    Google 1
+    Google 2


Abandoning type safety of api

Abandoning type safety of api

--- lib/types.coffee
+++ lib/types.coffee
@@ -1,44 +0,0 @@
-extend = (obj1, obj2) ->
-  _.extend(obj2, obj1)
-  obj2
-
-GitHub.api.types =
-  all: (args) ->
-    extend args,
-      type: 'boolean'
-      default: false
-
-  participating: (args) ->
-    extend args,
-      type: 'boolean'
-      default: false
-
-  since: (args) ->
-    extend args,
-      type: 'date:ISO 8061'
-      default: 'Time.now'
-
-  last_read_at: (args) ->
-    extend args,
-      type: 'date:ISO 8601'
-      default: 'Time.now'
-
-  subscribed: (args) ->
-    extend args,
-      type: 'boolean'
-
-  ignored: (args) ->
-    extend args,
-      type: 'boolean'
-
-  sort: (args) ->
-    extend args,
-      type: 'string'
-      choice: ['created', 'updated']
-      default: 'created'
-
-  direction: (args) ->
-    extend args,
-      doc: 'One of asc (ascending) or desc (descending).'
-      type: 'string'
-      choice: ['asc', 'desc']


unnecessary

unnecessary

--- noddy/service/v2/find.coffee
+++ noddy/service/v2/find.coffee
@@ -4,6 +4,7 @@

 #oab_find.remove '*'
 #oab_catalogue.remove '*'
+# an unnecessary change

 API.service.oab.ftitle = (title) ->
   # a useful way to show a title (or other string) as one long string with no weird characters


= vs == bugfix

= vs == bugfix

--- src/compiler.coffee
+++ src/compiler.coffee
@@ -108,7 +108,7 @@
         next_block.compile @stack[..], @locals[..]

 cmpMap =
-  eq: '='
+  eq: '=='
   ne: '!=='
   lt: '<'
   ge: '>='


update keymap

update keymap

--- keymaps/autohide-tree-view.cson
+++ keymaps/autohide-tree-view.cson
@@ -1,5 +1,3 @@
-'.platform-linux, .platform-win32, atom-workspace':
+'atom-workspace':
   'ctrl-\\': 'autohide-tree-view:toggle'
-
-'.platform-darwin, atom-workspace':
   'cmd-\\': 'autohide-tree-view:toggle'


Search completion; fix synchronisation issue.

--- lib/utils.coffee
+++ lib/utils.coffee
@@ -274,14 +274,14 @@
     @rotate()

 # This is a simple class for the common case where we want to use some data value which may be immediately
-# available, or for which we may have to wait.  It implements the use-immediately-or-wait queue, and calls the
-# function to fetch the data asynchronously.
+# available, or for which we may have to wait.  It implements a use-immediately-or-wait queue, and calls the
+# fetch function to fetch the data asynchronously.
 class AsyncDataFetcher
   constructor: (fetch) ->
     @data = null
     @queue = []
-    fetch (@data) =>
-      Utils.nextTick =>
+    Utils.nextTick =>
+      fetch (@data) =>
         callback @data for callback in @queue
         @queue = null


cleanup and document moving/overwriting logic

--- lib/utils.coffee
+++ lib/utils.coffee
@@ -60,24 +60,32 @@
   {newRange, overwritten}

 rotateChars = (selection, direction, {overwritten}={}) ->
+  # e.g.
+  # Assume situation where moving `pple` perfectly cover existing `lemon`
+  #  overwritten =   |1|2|3|4| <- this is hidden by chars `apple`
+  #  Text =        |Z|A|B|C|D|E|
+  #  Moving =        |A|B|C|D|   <- now moving |ABCD|(visually selected)
+  #  Chars(R) =      |A|B|C|D|E| <- Chars when moving 'Right' selected one char right
+  #  Chars(L) =    |Z|A|B|C|D|  <- Chars when moving 'Left', selected one char left
+  #
+  # - overwritten.length = 4
+  # - chars.length = 5(thus always 1 length longer than overwritten)
+  #
+  overwritten ?= []
   chars = selection.getText().split('')
   switch direction
     when 'right'
-      [other..., char] = chars
-      if overwritten?
-        chars = [overwritten.shift(), other...]
-        overwritten.push(char)
-      else
-        chars = [char, other...]
-        overwritten = []
+      # Move right-most(last in array) char to left-most(first in array)
+      # From: overwritten = 1234, chars = ABCDE
+      # To:   overwritten = 234E, chars = 1ABCD ('E' was hidden, '1' appeared)
+      overwritten.push(chars.pop()) # overwritten = 1234E, chars = ABCD
+      chars.unshift(overwritten.shift()) # overwritten = 234E, chars = 1ABCD
     when 'left'
-      [char, other...,] = chars
-      if overwritten?
-        chars = [other..., overwritten.pop()]
-        overwritten.unshift(char)
-      else
-        chars = [other..., char]
-        overwritten = []
+      # Move left-most(first in array) char to right-most(last in array)
+      # From: overwritten = 1234, chars = ZABCD
+      # To:   overwritten = Z123, chars = ABCD4 ('Z' was hidden, '4' appeared)
+      overwritten.unshift(chars.shift()) # overwritten = Z1234, chars = ABCD
+      chars.push(overwritten.pop()) # overwritten = Z123, chars = ABCD4

   newRange = selection.insertText(chars.join(""))
   {newRange, overwritten}


Register callback with UUID before dispatch is called

--- src/client.coffee
+++ src/client.coffee
@@ -44,7 +44,8 @@
   # Returns nothing
   ready: (callback) ->
     @_createFrame @serverUrl, =>
-      uuid = @_dispatch('getEndpoints', true)
+      uuid = @_generateUuid()
+      @_dispatch(uuid, 'getEndpoints', true)

       @_registerCallback uuid, (methods) =>
         @_createEndpoints(methods)
@@ -92,9 +93,9 @@
       do (endpoint) =>
         @[endpoint] = (args...) ->
           [data, callback] = @_parseArgs(args)
-          uuid = @_dispatch(endpoint, data)
+          uuid = @_generateUuid()
           @_registerCallback(uuid, callback) if callback?
-
+          @_dispatch(uuid, endpoint, data)
     @

   # Take an artibuarty number of arguments and determine which is the data and
@@ -126,9 +127,7 @@
   # using postMessage
   #
   # Returns a String of the Message's UUID
-  _dispatch: (method, data) ->
-    uuid = @_generateUuid()
-
+  _dispatch: (uuid, method, data) ->
     payload = @_payload(uuid, method, data)
     @_frame.postMessage payload, '*'
     uuid


Fix up naming of price vs amount.

Fix up naming of price vs amount.

--- src/coffee.coffee
+++ src/coffee.coffee
@@ -185,20 +185,19 @@
       barista: barista
       dibs: [barista],
       messageMetadata: msg.envelope.message?.metadata,
-      brewing.bounty = bountyAmount

     robot.brain.save()

-    if bounty.amount > 0 and barista is not bounty.requester
+    if bounty.price > 0 and barista is not bounty.requester
       msg.send "@team A bountied Brew has been started by @#{brewing.barista}! #{statusEmoji.random('success')}\n" +
-          "@#{brewing.barista} will get an extra #{bounty.amount} coffeeconomy points for this brew."
+          "@#{brewing.barista} will get an extra #{bounty.price} coffeeconomy points for this brew."
           "To grab a spot use: #{robot.alias}dibs\n" +
           "To end the brew use: #{robot.alias}fresh pot"

       dibs(bounty.requester)
-    if bounty.amount > 0 and barista is bounty.requester
+    if bounty.price > 0 and barista is bounty.requester
       msg.send "Hey @{bounty.requester} can't collect your own bounty! Your bounty has been cancelled."
-      bounty.amount = 0
+      bounty.price = 0
     else
       msg.send "@team Brew started by @#{brewing.barista}! #{statusEmoji.random('success')}\n" +
           "To grab a spot use: #{robot.alias}dibs\n" +


remove quit commands

remove quit commands

--- atom.symlink/keymap.cson
+++ atom.symlink/keymap.cson
@@ -1,7 +1,5 @@
 'body':
   'cmd-q': 'unset!'
-  'cmd-escape': 'application:quit'
-  'alt-cmd-q': 'application:quit'

   # better arrows
   'alt-j': 'core:move-left'