Fix errors & warnings presented by coffeelint

--- src/d3.timeslider.coffee
+++ src/d3.timeslider.coffee
@@ -34,7 +34,7 @@
         @options.pixelPerDay = @options.minPixelPerDay if @options.pixelPerDay < @options.minPixelPerDay

         # scales
-        @scales =
+        @scales =
             x: d3.time.scale.utc()
                 .domain([ @options.start, @options.end ])
                 .range([0, @numberOfDays * @options.pixelPerDay])
@@ -42,7 +42,7 @@
                 .range([ 0, @options.height ])

         # axis
-        @axis =
+        @axis =
             x: d3.svg.axis()
                 .scale(@scales.x)
                 .ticks(d3.time.days.utc, 3)
@@ -55,7 +55,7 @@
             .call(@axis.x)

        # grid
-        @grid =
+        @grid =
             x: d3.svg.axis()
                 .scale(@scales.x)
                 .ticks(d3.time.days.utc, 1)
@@ -71,18 +71,18 @@
             .call(@grid.x)

         # brush
+        event = =>
+            new CustomEvent('selectionChanged', {
+                detail: {
+                    start: @brush.extent()[0],
+                    end: @brush.extent()[1]
+                }
+                bubbles: true,
+                cancelable: true
+            })
         @brush = d3.svg.brush()
             .x(@scales.x)
-            .on('brushend', =>
-                element.dispatchEvent(new CustomEvent('selectionChanged', {
-                    detail: {
-                        start: @brush.extent()[0],
-                        end: @brush.extent()[1]
-                    }
-                    bubbles: true,
-                    cancelable: true
-                }))
-            )
+            .on('brushend', => element.dispatchEvent(event()))
             .extent([@options.brush.start, @options.brush.end])

         @root.append('g')
@@ -103,26 +103,28 @@

             # register event handlers for mousemove (to handle the real dragging logic) and mouseup
             # to deregister unneeded handlers
+            move = =>
+                element.dragging.position[0] += d3.event.pageX - element.dragging.lastPosition[0]
+                element.dragging.position[1] += d3.event.pageY - element.dragging.lastPosition[1]
+                element.dragging.lastPosition = [d3.event.pageX, d3.event.pageY]
+
+                width = Math.ceil(d3.select(@element).select('svg').style('width').slice(0, -2))
+
+                # TODO Allow dragging over the boundaries, but snap back afterwards
+                if element.dragging.position[0] > 0
+                    element.dragging.position[0] = 0
+                else if ((Number) element.dragging.position[0] + @scales.x.range()[1]) < width
+                    element.dragging.position[0] = width - @scales.x.range()[1]
+                    console.log("Dragging Position #{element.dragging.position}")
+                @root.attr('transform', "translate(#{element.dragging.position[0]}, 0)")
+            up = =>
+                d3.select(document)
+                    .on('mousemove', null)
+                    .on('mouseup', null)
+
             d3.select(document)
-                .on('mousemove', =>
-                    element.dragging.position[0] += d3.event.pageX - element.dragging.lastPosition[0]
-                    element.dragging.position[1] += d3.event.pageY - element.dragging.lastPosition[1]
-                    element.dragging.lastPosition = [d3.event.pageX, d3.event.pageY]
-
-                    width = Math.ceil(d3.select(@element).select('svg').style('width').slice(0, -2))
-
-                    # TODO Allow dragging over the boundaries, but snap back afterwards
-                    if element.dragging.position[0] > 0
-                        element.dragging.position[0] = 0
-                    else if ((Number) element.dragging.position[0] + @scales.x.range()[1]) < width
-                        element.dragging.position[0] = width - @scales.x.range()[1]
-                        console.log("Dragging Position #{element.dragging.position}")
-                    @root.attr('transform', "translate(#{element.dragging.position[0]}, 0)")
-
-                )
-                .on('mouseup', =>
-                    d3.select(document).on('mousemove', null).on('mouseup', null)
-                )
+                .on('mousemove', => move())
+                .on('mouseup', => up())

             # prevent default events
             d3.event.preventDefault()
@@ -139,10 +141,10 @@
             @options.pixelPerDay = (@options.width - 20) / @numberOfDays
             @options.pixelPerDay = @options.minPixelPerDay if @options.pixelPerDay < @options.minPixelPerDay

-            # update scale
+            # update scale
             @scales.x.range([0, @numberOfDays * @options.pixelPerDay])

-            # update brush
+            # update brush
             @brush.x(@scales.x).extent(@brush.extent())

             # repaint the axis, scales and the brush
@@ -152,7 +154,7 @@

         d3.select(window).on('resize', resize)

-        # zooming
+        # zooming
         # (done via a seperate function, because we need to bind to two differen event listeners)
         zoom = =>
             if @debug
@@ -173,12 +175,12 @@

             console.log("Zooming to level #{@element.zoomLevel}") if @debug

-            # update scale
+            # update scale
             @scales.x.range([0, @numberOfDays * @options.pixelPerDay])

             # update axis
             # TODO make cleaner
-            switch
+            switch
                 when @element.zoomLevel < -7
                     @axis.x.ticks(d3.time.months.utc, 2).tickFormat(d3.time.format.utc('%Y-%m'))
                     @grid.x.ticks(d3.time.months.utc, 1)
@@ -199,7 +201,7 @@
                     @grid.x.ticks(d3.time.days.utc, 1)
                 when @element.zoomLevel < 4
                     @axis.x.ticks(d3.time.days.utc, 1).tickFormat(d3.time.format.utc('%Y-%m-%d'))
-                    @grid.x.ticks(d3.time.hours.utc, 6)
+                    @grid.x.ticks(d3.time.hours.utc, 6)
                 when @element.zoomLevel <= 5
                     @axis.x.ticks(d3.time.hours.utc, 12).tickFormat(d3.time.format.utc('%Y-%m-%d %I:%M'))
                     @grid.x.ticks(d3.time.hours.utc, 3)
@@ -213,7 +215,7 @@
                     @axis.x.ticks(d3.time.minutes.utc, 90).tickFormat(d3.time.format.utc('%Y-%m-%d %I:%M'))
                     @grid.x.ticks(d3.time.minutes.utc, 30)

-            # update brush
+            # update brush
             @brush.x(@scales.x).extent(@brush.extent())

             # repaint the scales and axis
@@ -246,6 +248,6 @@

         d3.select(@element).select('g.brush').call(@brush.extent([start, end]))
         true
-
+
 # Export the TimeSlider object for use in the browser
 this.TimeSlider = TimeSlider


debug info

debug info

--- app/js/app.coffee
+++ app/js/app.coffee
@@ -105,6 +105,8 @@
 app.config ($idleProvider, $translateProvider, $tooltipProvider, $compileProvider) ->

     $compileProvider.debugInfoEnabled(false);
+    # set this to false in production to gain performance boost
+    # use angular.reloadWithDebugInfo() to reload the page and obtain debug capability

     $tooltipProvider.options { appendToBody: true }


computecontroller: update plans after paypal request finishes

--- client/app/lib/providers/computecontroller.coffee
+++ client/app/lib/providers/computecontroller.coffee
@@ -50,7 +50,7 @@
         @stateChecker.start()

         kd.singletons
-          .paymentController.on 'UserPlanUpdated', =>
+          .paymentController.on ['UserPlanUpdated', 'PaypalRequestFinished'], =>
             @lastKnownUserPlan = null
             @fetchUserPlan()


test(network): remove unwanted ssh filter in tcp wait

--- packages/network/test/tcp/wait.coffee
+++ packages/network/test/tcp/wait.coffee
@@ -64,7 +64,6 @@
   describe 'run', ->

     they 'a single host and a single port', ({ssh}) ->
-      return if ssh
       srv = server()
       await nikita
         $ssh: ssh


Solving small issue with save button

Solving small issue with save button

--- client/src/app/game/edit/header/controller.coffee
+++ client/src/app/game/edit/header/controller.coffee
@@ -7,9 +7,10 @@
     $scope.currentGame = currentGame
     $scope.gameTime = gameTime

-.controller 'MenuCtrl', ($scope, $location, loggedUser, games, loginDialog, importExportDialog) ->
+.controller 'MenuCtrl', ($scope, $location, loggedUser, games, currentGame, loginDialog, importExportDialog) ->
     $scope.user = loggedUser
     $scope.games = games
+    $scope.currentGame = currentGame
     $scope.loginDialog = loginDialog
     $scope.importExportDialog = importExportDialog
     $scope.loadGame = -> $location.path('/game/list')


Add tests for nested property observers.

--- spec/coffee/Deft/mvc/ViewController.coffee
+++ spec/coffee/Deft/mvc/ViewController.coffee
@@ -1487,8 +1487,6 @@

 		it( 'should attach listeners to observed objects', ->

-			console.log( 'starting attach observer test' )
-
 			Ext.define( 'ExampleClass',
 				extend: 'Deft.mvc.ViewController'

@@ -1498,19 +1496,15 @@

 				observe:
 					messageBus:
-						parentMessage: "parentMessageHandler" #host: @, target: @messageBus, fn: host.parentMessageHandler
+						parentMessage: "parentMessageHandler"
 					store:
-						beforesync: "storeHandler" #host: @, target: @store, fn: host.storeHandler
-					'store.data':
-						add: "storeDataHandler" #host: @store, target: @store.data, fn: host.storeDataHandler
+						beforesync: "storeHandler"

 				parentMessageHandlerCalled: false
 				storeHandlerCalled: false
-				storeDataHandlerCalled: false

 				parentMessageHandler: ( eventData ) -> @parentMessageHandlerCalled = eventData
 				storeHandler: ( eventData ) -> @storeHandlerCalled = eventData
-				storeDataHandler: ( eventData ) -> @storeDataHandlerCalled = eventData
 			)

 			Ext.define( 'ExampleSubClass',
@@ -1528,7 +1522,6 @@

 			messageBus = Ext.create( 'Ext.util.Observable' )
 			store = Ext.create( 'Ext.data.ArrayStore' )
-			#store.data - event: add

 			exampleInstance = Ext.create( 'ExampleSubClass',
 				messageBus: messageBus
@@ -1561,12 +1554,75 @@
 				expect( exampleInstance.storeHandlerCalled ).toEqual( 'beforeSyncEventData' )
 			)

+		)
+
+		it( 'should attach listeners to observed objects using nested property declaration', ->
+
+			Ext.define( 'ExampleClass',
+				extend: 'Deft.mvc.ViewController'
+
+				config:
+					messageBus: null
+					store: null
+
+				observe:
+					messageBus:
+						parentMessage: "parentMessageHandler"
+					'store.data':
+						add: "storeDataHandler"
+
+				parentMessageHandlerCalled: false
+				storeDataHandlerCalled: false
+
+				parentMessageHandler: ( eventData ) -> @parentMessageHandlerCalled = eventData
+				storeDataHandler: ( eventData ) -> @storeDataHandlerCalled = eventData
+			)
+
+			Ext.define( 'ExampleSubClass',
+				extend: 'ExampleClass'
+
+				observe:
+					'store.filters':
+						replace: "storeFilterHandler"
+
+				storeFilterHandlerCalled: false
+
+				storeFilterHandler: ( eventData ) ->
+					@storeFilterHandlerCalled = eventData
+			)
+
+			messageBus = Ext.create( 'Ext.util.Observable' )
+			store = Ext.create( 'Ext.data.ArrayStore' )
+
+			exampleInstance = Ext.create( 'ExampleSubClass',
+				messageBus: messageBus
+				store: store
+			)
+
+			# Cannot just spy on the handler methods because messageBus listener will always reference the original method, not the spy.
+			waitsFor( ( -> exampleInstance.parentMessageHandlerCalled ), "Parent message handler was not called.", 1000 )
+
+			parentEventData = { value1: true, value2: false }
+			messageBus.fireEvent( 'parentMessage', parentEventData )
+
+			runs( ->
+				expect( exampleInstance.parentMessageHandlerCalled ).toEqual( parentEventData )
+			)
+
 			waitsFor( ( -> exampleInstance.storeDataHandlerCalled ), "Nested store.data handler was not called.", 1000 )

 			store.data.fireEvent( 'add', 'storeDataAddEventData' )

 			runs( ->
 				expect( exampleInstance.storeDataHandlerCalled ).toEqual( 'storeDataAddEventData' )
+			)
+
+			waitsFor( ( -> exampleInstance.storeFilterHandlerCalled ), "Nested store.filter handler was not called.", 1000 )
+
+			store.filters.fireEvent( 'replace', 'storeFilterReplaceEventData' )
+
+			runs( ->
+				expect( exampleInstance.storeFilterHandlerCalled ).toEqual( 'storeFilterReplaceEventData' )
 			)
 		)


Fixes #2714 - Roles and Users selection in Overview administration UI ambiguous.

--- app/assets/javascripts/app/models/overview.coffee
+++ app/assets/javascripts/app/models/overview.coffee
@@ -5,8 +5,8 @@
   @configure_attributes = [
     { name: 'name',       display: 'Name',                tag: 'input',    type: 'text', limit: 100, 'null': false },
     { name: 'link',       display: 'Link',                readonly: 1 },
-    { name: 'role_ids',   display: 'Available for Role',  tag: 'column_select', multiple: true, null: false, relation: 'Role', translate: true },
-    { name: 'user_ids',   display: 'Available for User',  tag: 'column_select', multiple: true, null: true,  relation: 'User', sortBy: 'firstname' },
+    { name: 'role_ids',   display: 'Available for the following roles',    tag: 'column_select', multiple: true, null: false, relation: 'Role', translate: true },
+    { name: 'user_ids',   display: 'Restrict to only the following users', tag: 'column_select', multiple: true, null: true,  relation: 'User', sortBy: 'firstname' },
     { name: 'organization_shared', display: 'Only available for Users with shared Organization', tag: 'select', options: { true: 'yes', false: 'no' }, default: false, null: true },
     { name: 'out_of_office', display: 'Only available for Users which are replacements for other users.', tag: 'select', options: { true: 'yes', false: 'no' }, default: false, null: true },
     { name: 'condition',  display: 'Conditions for shown Tickets', tag: 'ticket_selector', null: false, out_of_office: true },


Fix typo

Fix typo

--- server/api/register.coffee
+++ server/api/register.coffee
@@ -18,7 +18,7 @@
 import logger from '../log'

 imapClient = undefined
-if process.env["EMAIL_USER"] and process.env("EMAIL_PASSWORD")
+if process.env["EMAIL_USER"] and process.env["EMAIL_PASSWORD"]
     imapClient = new ImapFlow
         host: 'imap.gmail.com',
         port: 993,


Changed: remove "scroll past end" in Atom, it's so boring

--- dotfiles/atom/config.cson
+++ dotfiles/atom/config.cson
@@ -31,7 +31,6 @@
     invisibles:
       space: "‧"
     lineHeight: 1.45
-    scrollPastEnd: true
     showIndentGuide: true
     showInvisibles: true
   "exception-reporting":


refactor example server

refactor example server

--- example/server.coffee
+++ example/server.coffee
@@ -1,27 +1,13 @@
-http = require('http')
-url = require('url')
 path = require('path')
-fs = require('fs')
+express = require('express')
+serveStatic = require('serve-static')
+pak = require(path.join(__dirname, '..', 'package.json'))
+imageList = require(path.join(__dirname, '..', 'src', 'data', 'images.json'))

 port = parseInt(process.argv[2], 10) or 8888
-pak = require(path.join(__dirname, '..', 'package.json'))
-json = require(path.join(__dirname, '..', 'src', 'data', 'images.json'))
+staticDirectory = path.join(__dirname, 'static')

-# create a server that either returns json image list or index html
-http.createServer((request, response) ->
-  if url.parse(request.url).pathname is '/images.json'
-    response.writeHead 200
-    response.write JSON.stringify(json)
-    response.end()
-  else
-    fs.readFile path.join(__dirname, 'index.html'), (error, content) ->
-      if error
-        response.writeHead 500
-        response.end error
-      else
-        response.writeHead 200,
-          'Content-Type': 'text/html'
-        response.end content, 'utf-8'
-).listen port
-
-console.log "View images for #{pak.name} at http://localhost:#{port}"+app = express()
+app.use(express.static(staticDirectory))
+app.get '/images.json',  (req, res) -> res.send(JSON.stringify(imageList))
+app.listen port, -> console.log "\n #{pak.name} @ http://localhost:#{port}"


Add .timeago jQuery tooltip

Add .timeago jQuery tooltip

--- app/assets/javascripts/jquery.timeago.load.coffee
+++ app/assets/javascripts/jquery.timeago.load.coffee
@@ -1,3 +1,4 @@
 $ ->
   # timeago
-  $('abbr.timeago').timeago();
+  $('abbr.timeago').timeago()
+  $('abbr.timeago').tooltip()


Removed duplicate callback of $.fn.application.

--- app/assets/javascripts/koi/application/koi.coffee
+++ app/assets/javascripts/koi/application/koi.coffee
@@ -44,7 +44,6 @@
     [ f ] = args

     fStar = -> $( @ ).each ( i, e ) -> $.application.call( e, $(e), f )
-    $ => @livequery fStar
     $ => if live then @livequery fStar else fStar.call @
     @


Should JSON-encode request before sending

--- app/assets/javascripts/backbone/models/commit_request.js.coffee
+++ app/assets/javascripts/backbone/models/commit_request.js.coffee
@@ -48,7 +48,7 @@
     @trigger("sending_commit_request")
     $.ajax gon.commit_request_path,
       type: "POST"
-      data: commit_request: request
+      data: commit_request: JSON.stringify(request)
       success: (data) => @success(data)
       error: (jqXHR, textStatus, errorThrown) =>
         console.log("Error: ", jqXHR, textStatus, errorThrown)


Fix ApplicationService and Aggregate delegation bug at the BoundedContext

--- src/bounded_context.coffee
+++ src/bounded_context.coffee
@@ -54,13 +54,15 @@

       for commandName, commandMethodName of applicationService.commands
         # TODO: check duplicates, warn and do some logging
-        @_applicationServiceCommands[commandName] = ->
-          applicationService[commandMethodName].apply applicationService, arguments
+        do (commandName, commandMethodName, applicationService) =>
+          @_applicationServiceCommands[commandName] = ->
+            applicationService[commandMethodName].apply applicationService, arguments

       for queryName, queryMethodName of applicationService.queries
         # TODO: check duplicates, warn and do some logging
-        @_applicationServiceQueries[queryName] = ->
-         applicationService[queryMethodName].apply applicationService, arguments
+        do (queryName, queryMethodName, applicationService) =>
+          @_applicationServiceQueries[queryName] = ->
+            applicationService[queryMethodName].apply applicationService, arguments

       applicationService.initialize?()

@@ -96,4 +98,4 @@
     @_domainEventService.on eventName, eventHandler

-module.exports = BoundedContext+module.exports = BoundedContext


added packager port checking function

added packager port checking function

--- natal.coffee
+++ natal.coffee
@@ -5,6 +5,8 @@
 # MIT License

 fs      = require 'fs'
+net     = require 'net'
+http    = require 'http'
 crypto  = require 'crypto'
 child   = require 'child_process'
 cli     = require 'commander'
@@ -19,6 +21,7 @@
 projNameHyphRx  = /\$PROJECT_NAME_HYPHENATED\$/g
 projNameUnderRx = /\$PROJECT_NAME_UNDERSCORED\$/g
 rnVersion       = '0.13.0-rc'
+rnPackagerPort  = 8081
 podMinVersion   = '0.38.2'
 process.title   = 'natal'

@@ -55,6 +58,23 @@

 toUnderscored = (s) ->
   s.replace(camelRx, '$1_$2').toLowerCase()
+
+
+checkPort = (port, cb) ->
+  sock = net.connect {port}, ->
+    sock.end()
+    req = http.get "http://localhost:#{port}/status", (res) ->
+      data = ''
+      res.on 'data', (chunk) -> data += chunk
+      res.on 'end', ->
+        cb data.toString() isnt 'packager-status:running'
+
+    .on 'error', -> cb true
+    .setTimeout 3000
+
+  sock.on 'error', ->
+    sock.end()
+    cb false

 writeConfig = (config) ->


append '?' char if needed

append '?' char if needed

--- app/assets/javascripts/uploadcare/settings.coffee
+++ app/assets/javascripts/uploadcare/settings.coffee
@@ -209,11 +209,14 @@
         encodedUrl = encodeURIComponent(url)
         justAppend = /\=$/.test(settings.previewProxy)
         useAmpersand = /[^\&\?]$/.test(settings.previewProxy)
-
-        queryToAppend = if justAppend then encodedUrl else
+        addQuestionSign = not /\?/.test(settings.previewProxy)
+
+        queryPart = if justAppend then encodedUrl else
           if useAmpersand then "&url=#{encodedUrl}" else "url=#{encodedUrl}"

-        utils.normalizeUrl(settings.previewProxy) + queryToAppend
+        queryPart = '?' + queryPart if addQuestionSign
+
+        utils.normalizeUrl(settings.previewProxy) + queryPart

     settings


sks-108 - clicking row should work similar as ...

--- app/assets/javascripts/views/users_view.js.coffee
+++ app/assets/javascripts/views/users_view.js.coffee
@@ -2,16 +2,23 @@
   elementId: 'kudos-users-view'

   didInsertElement: ->
-    # show hidden content on more button click
-    @.$('#users-list').on 'click', '.more', (event) ->
-      $this = $ this
-      $coworker = $this.parents '.coworker'
-      $active = $coworker.siblings('.form-visible')
+    showRow = ($row) ->
+      $active = $row.siblings('.form-visible')

       # first hide all the active element
       $active.toggleView()

       # then show the clicked one
-      $coworker.toggleView() if $coworker.get() isnt $active.get()
+      $row.toggleView() if $row.get() isnt $active.get()

-      event.preventDefault()+    # show hidden content on more button click
+    @.$('#users-list').on 'click', '.more', (event) ->
+      $row = $(this).parents '.coworker'
+      showRow $row
+
+      return false
+
+    @.$('#users-list').on 'click', '.coworker', (event) ->
+      showRow $ this
+
+      return false


If click happens inside popup don't close it

--- app/assets/javascripts/species/views/application_view.js.coffee
+++ app/assets/javascripts/species/views/application_view.js.coffee
@@ -5,4 +5,4 @@
       $("div#banner").slideUp "normal"

   click: (event) ->
-    $('.popup-clickable').hide()
+    $('.popup-clickable').hide() unless $(event.target).closest('.popup-clickable').length


Open login always in top slot.

Open login always in top slot.

--- core/htdocs_source/src/pods/openxpki/route.coffee
+++ core/htdocs_source/src/pods/openxpki/route.coffee
@@ -33,7 +33,11 @@
         entries = navEntries.reduce (p, n) ->
             p.concat(n, n.entries||[])
         , []
-        data.target = "top" if entries.findBy "key", req.model_id
+
+        if entries.findBy "key", req.model_id
+            data.target = "top"
+        else if req.model_id is "login"
+            data.target = "top"

         source = @get "source"
         source.set "page", req.model_id


Removed un-used code

Removed un-used code

--- app/assets/javascripts/milestone_select.js.coffee
+++ app/assets/javascripts/milestone_select.js.coffee
@@ -27,17 +27,6 @@
         )

         milestoneLinkNoneTemplate = '
None
'
-
-      extraOptions = [{
-        isAny: true
-        title: 'Any Milestone'
-      }, {
-        id: '0'
-        title: 'No Milestone'
-      }, {
-        id: '#upcoming'
-        title: 'Upcoming'
-      }]

       $dropdown.glDropdown(
         data: (term, callback) ->


Fix mouse controls again

Fix mouse controls again

--- app/assets/javascripts/oxalis/model/flycam.coffee
+++ app/assets/javascripts/oxalis/model/flycam.coffee
@@ -125,7 +125,7 @@
   moveActivePlane : (p) -> # vector of voxels in BaseVoxels
     p = Dimensions.transDim(p, @activePlane)
     ind = Dimensions.getIndices(@activePlane)
-    zoomFactor = 1 << @integerZoomSteps[@activePlane]
+    zoomFactor = Math.pow(2, @zoomSteps[@activePlane])
     scaleFactor = @scaleInfo.baseVoxelFactors
     delta = [p[0]*zoomFactor*scaleFactor[0], p[1]*zoomFactor*scaleFactor[1], p[2]*zoomFactor*scaleFactor[2]]
     # change direction of the value connected to space, based on the last direction


Got rid of the insert errors on the server

--- server/publications.coffee
+++ server/publications.coffee
@@ -62,7 +62,7 @@
           for key, value of root
             if name == value._name
               collections[name] = value
-          console.log e
+          console.log e unless collections[name]?

         set_up_collection(name, collections[name])


Added helper isRole().

Added helper isRole().

--- app/assets/javascripts/app/controllers/_application_controller.js.coffee
+++ app/assets/javascripts/app/controllers/_application_controller.js.coffee
@@ -19,6 +19,12 @@
       window.scrollTo( x, y )

     @delay( a, 0 )
+
+  isRole: (name) ->
+    return false if !window.Session.roles
+    for role in window.Session.roles
+      return true if role.name is name
+    return false

 #  # extend delegateEvents to unbind and undelegate
 #  delegateEvents: ->


Change dependencie call

Change dependencie call

--- app/assets/javascripts/backend/purchase_process/reconciliation.js.coffee
+++ app/assets/javascripts/backend/purchase_process/reconciliation.js.coffee
@@ -50,7 +50,7 @@

     E.reconciliation.displayReconciliateState(event)

-    @reconciliationModal= new ekylibre.modal('#purchase_process_reconciliation')
+    @reconciliationModal= new E.modal('#purchase_process_reconciliation')
     @reconciliationModal.getModal().modal 'hide'

@@ -127,7 +127,7 @@
         data: datas
         success: (data, status, request) ->

-          @reconciliationModal= new ekylibre.modal('#purchase_process_reconciliation')
+          @reconciliationModal= new E.modal('#purchase_process_reconciliation')
           @reconciliationModal.removeModalContent()
           @reconciliationModal.getModalContent().append(data)
           @reconciliationModal.getModal().modal 'show'


change twitter url

change twitter url

change What's happening? for Share a link with your followers

--- app/assets/javascripts/social-share-button.coffee
+++ app/assets/javascripts/social-share-button.coffee
@@ -8,6 +8,7 @@
     title = encodeURIComponent($(el).parent().data('title') || '')
     img = encodeURIComponent($(el).parent().data("img") || '')
     url = encodeURIComponent($(el).parent().data("url") || '')
+    via = encodeURIComponent($(el).parent().data("via") || '')
     if url.length == 0
       url = encodeURIComponent(location.href)
     switch site
@@ -16,7 +17,7 @@
       when "weibo"
         SocialShareButton.openUrl("http://service.weibo.com/share/share.php?url=#{url}&type=3&pic=#{img}&title=#{title}")
       when "twitter"
-        SocialShareButton.openUrl("https://twitter.com/home?status=#{title}: #{url}")
+        SocialShareButton.openUrl("https://twitter.com/intent/tweet?url=#{url}&text=#{title}&via=#{via}")
       when "douban"
         SocialShareButton.openUrl("http://shuo.douban.com/!service/share?href=#{url}&name=#{title}&image=#{img}")
       when "facebook"


Remove obsolete code

Remove obsolete code

--- h2o-web/src/main/steam/scripts/frame-list-view.coffee
+++ h2o-web/src/main/steam/scripts/frame-list-view.coffee
@@ -65,22 +65,6 @@
           else
             displayFrames frames

-      when 'compatibleWithModel'
-        #FIXME Need an api call to get "frames and compatible models for all frames compatible with a model"
-        _.requestModelAndCompatibleFrames predicate.modelKey, (error, data) ->
-          if error
-            #TODO handle errors
-          else
-            compatibleFramesByKey = indexBy (head data.models).compatible_frames, (frame) -> frame.key
-            _.requestFramesAndCompatibleModels (error, data) ->
-              if error
-                #TODO handle errors
-              else
-                compatibleFrames = filter data.frames, (frame) -> if compatibleFramesByKey[frame.key] then yes else no
-                # PP-74 hide raw frames from list
-                nonRawFrames = filter compatibleFrames, (frame) -> not frame.is_raw_frame
-                displayFrames nonRawFrames
-
     _predicate predicate
     return


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/engine_levels.coffee
+++ src/engine_levels.coffee
@@ -26,7 +26,7 @@
       engine.setState levelState

   ###*
-  Load the map for the next level.
+  Load map for the next level.

   engine.nextLevel()


fce: removed leftovers

fce: removed leftovers

Forget the checkboxes that were hardcoded in the database

--- app/assets/javascripts/lib/models/setting.coffee
+++ app/assets/javascripts/lib/models/setting.coffee
@@ -5,16 +5,15 @@
   isNew : -> false

   toggle_fce: ->
-    # there are 2 checkboxes!
     use_fce = !!$(this).attr('checked')
-    # update the other one
-    $(".inline_use_fce, #settings_use_fce").attr('checked', use_fce)
-    App.settings.save({use_fce: use_fce})
+    App.settings.save
+      use_fce: use_fce
     $('.fce_notice').toggle(use_fce)
     App.call_api()

   toggle_peak_load_tracking: ->
-    App.settings.save({track_peak_load: $("#track_peak_load_settings").is(':checked')})
+    App.settings.save
+      track_peak_load: $("#track_peak_load_settings").is(':checked')

   # Used by the bio-footprint dashboard item
   country: => @get('area_code').split('-')[0]


json repr of embed database

json repr of embed database

--- app/assets/javascripts/notebook/dataframe.coffee
+++ app/assets/javascripts/notebook/dataframe.coffee
@@ -70,7 +70,7 @@
             return schema.fields.map((c) ->
                 cell = {
                   'cl': c.type
-                  'value': row[c.name]
+                  'value': JSON.stringify(row[c.name])
                 }
                 return cell
             )


Delete branch bug fix

Delete branch bug fix

--- app/assets/javascripts/oxalis/model/route.coffee
+++ app/assets/javascripts/oxalis/model/route.coffee
@@ -441,7 +441,7 @@
     deletedNode = @activeNode
     @stateLogger.deleteNode(deletedNode, @activeTree.treeId)

-    @deleteBranch(deletedNode.id)
+    @deleteBranch(deletedNode)

     if deletedNode.neighbors.length > 1
       # Need to split tree


Use Datatables API to control refining table

--- src/coffee/refining.coffee
+++ src/coffee/refining.coffee
@@ -9,41 +9,29 @@

 #alert oreList
 #alert "3333"
-
+refiningTable = null
 refineMe = []
 #accepts optional array of values as 2nd parameter for parameterized queries

 AddNewRefiningElement = ->
-  itemName = document.getElementById("oreInput1").value
-  Quantity = document.getElementById("inputQuantity").value
-  found = false
-  i = 0
-  while i < refineMe.length
-    if refineMe[i][0] == itemName
-      found = true
-      old = eval(refineMe[i][1])
-      old += eval(Quantity)
-      refineMe[i][1] = old
-    i++
-  t = $("#refiningSource").DataTable()
-  if !found
-    row = new Array
-    row.push itemName
-    row.push Quantity
-    refineMe.push row
-    #-t.row.add(row);
-  t.clear()
-  $(refineMe).each ->
-    t.row.add this
-    return
-  t.draw()
+  Quantity = parseInt($("#inputQuantity").val(), 10)
+  unless isNaN(Quantity)
+    itemName = $("#oreInput1").val()
+    itemRow = refiningTable.column(0).data().indexOf(itemName)
+
+    if itemRow < 0 # Not found
+      refiningTable.row.add([itemName, Quantity])
+    else # Found
+      itemCell = refiningTable.cell(itemRow, 1) # Selects the right cell
+      dat = itemCell.data() # Pulls data from a different cell? wtf?!
+      itemCell.data(dat + Quantity)
+    refiningTable.draw()
   return

-$(document).ready ->
-  $("#refiningSource").DataTable
+$ ->
+  refiningTable = $("#refiningSource").DataTable
     "paging": false
     "searching": false
-    data: refineMe
     columns: [
       { title: "Ore" }
       { title: "Quantity" }


Use CoffeeScript syntax for rowData check

--- src/coffee/refining.coffee
+++ src/coffee/refining.coffee
@@ -19,7 +19,7 @@
     itemName = $("#oreInput1").val()

     rowData = refiningTable.row((rowIdx) ->
-      if refiningTable.cell(rowIdx, 0).data() == itemName then true else false
+      return refiningTable.cell(rowIdx, 0).data() is itemName
     ).index()

     if rowData == undefined # Not found


Missed a lint

Missed a lint

--- src/simple.coffee
+++ src/simple.coffee
@@ -18,7 +18,7 @@
     "simple(#{@value})"

   # Convert to a string when inspecting
-  #
+  #
   # @return [String]
   inspect: (depth, opts) ->
     "simple(#{@value})"


More fault tolerant SeriesGraph

More fault tolerant SeriesGraph

--- widgets/series_graph/series_graph.coffee
+++ widgets/series_graph/series_graph.coffee
@@ -21,7 +21,8 @@
     palette = new Rickshaw.Color.Palette({scheme: scheme})

     seriesCombined = []
-    for data,i in @get('series')
+    series = @get('series') ? []
+    for data,i in series
       seriesCombined[i] = {data: data, color: palette.color()}

     @graph = new Rickshaw.Graph(


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/engine_selector.coffee
+++ src/engine_selector.coffee
@@ -70,7 +70,7 @@
     Object.extend results, instanceMethods

   first: (selector) ->
-    self.find(selector)
+    self.find(selector).first()

 Object.extend Engine.Selector,
   parse: (selector) ->


Implement getPath() in markdown preview view

This allows it to be shown in the tree view when the
reveal command is triggered.

--- lib/markdown-preview-view.coffee
+++ lib/markdown-preview-view.coffee
@@ -29,6 +29,9 @@
   getUri: ->
     "markdown-preview:#{@buffer.getPath()}"

+  getPath: ->
+    @buffer.getPath()
+
   setErrorHtml: ->
     @html $$$ ->
       @h2 'Previewing Markdown Failed'


check if the app has the proper settings, otherwise show a warning

--- server/main.coffee
+++ server/main.coffee
@@ -1,4 +1,9 @@
 import { Meteor } from 'meteor/meteor';

 Meteor.startup ->
+  unless Meteor.settings.public.ddpServer
+    console.warn "ddpServer property not set!"
+    console.warn "Make sure your settings file looks something like",
+      public: ddpServer: 'http//my-ddp-server.com'
+
   console.log 'App started'


One more mention gone

One more mention gone

--- lib/app.coffee
+++ lib/app.coffee
@@ -6,7 +6,6 @@
 handlebars = require 'express-handlebars'
 bodyParser = require 'body-parser'
 morgan = require 'morgan'
-expressLess = require 'express-less'
 favicon = require 'serve-favicon'
 mincer = require 'mincer'


fix loading promise status

fix loading promise status

--- app/builtins.coffee
+++ app/builtins.coffee
@@ -190,7 +190,7 @@
     displayName: 'PromiseStatusComponent'
     mixins: [Context.ContextAwareMixin]
     render: ->
-      if @state?
+      if @state?.duration?
         ms = @state.duration
         duration = if ms >= 1000
           s = (ms / 1000).toFixed 1


NEW-FUNC Yield global replace attribute

NEW-FUNC Yield global replace attribute

--- src/helpers/yield.coffee
+++ src/helpers/yield.coffee
@@ -1,6 +1,7 @@
 class Neck.Helper.yield extends Neck.Helper
-  attributes: ['yieldView']
+  attributes: ['yieldView', 'yieldReplace']
   template: true
+  replace: false

   constructor: ->
     super
@@ -23,6 +24,8 @@
     if @scope.yieldView
       @append @scope.yieldView

+    @replace or= @scope.yieldReplace
+
   _createController: (controllerPath, params, parent)->
     Controller = Neck.DI.load(controllerPath, type: 'controller')
     controller = new Controller template: "#{controllerPath}", params: params
@@ -40,7 +43,7 @@

     controller

-  append: (controllerPath, params, refresh = false, replace = false)->
+  append: (controllerPath, params, refresh = false, replace = @replace)->
     if replace and @_yieldChild
       if controllerPath is @_yieldChild._yieldPath and not refresh
         @_yieldChild._yieldChild?.remove()


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/metered.coffee
+++ src/metered.coffee
@@ -27,7 +27,7 @@

 someOtherObject.meter 'turbo'
 # => Sets up a turbo meter that will be drawn during the someOtherObject overlay event.
-# Since neither turbo maxTurbo were provided, they are both set to 100
+# Since neither turbo maxTurbo were provided, they are both set to 100.

 # now player has all the methods provided by this module


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/metered.coffee
+++ src/metered.coffee
@@ -1,6 +1,7 @@
 ###*
 The Metered module provides a simple drop-in
 meter ui to track arbitrary numeric attributes.
+

 player = Core


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/metered.coffee
+++ src/metered.coffee
@@ -1,7 +1,7 @@
 Metered = (I={}, self) ->
   Object.reverseMerge I,
     meters: []
-
+

   self.bind 'overlay', (canvas) ->
     I.meters.each (meterData) ->


Issue #81: simplify Atom settings

Issue #81: simplify Atom settings

--- tools/atom-plugin/language-micro/settings/language-micro.cson
+++ tools/atom-plugin/language-micro/settings/language-micro.cson
@@ -7,12 +7,8 @@
 			| \\bas\\b[^(]*\\([^)]*\\).*$
 			| \\(\\s*$
 			| ^\\s*\\)
-			| \\bif\\b.*$
 		'
 		'decreaseIndentPattern': '(?x)
 			^\\s*;
-			| ^\\s*\\[\\];
-			| ^\\s*\\{\\};
-			| ^\\s*this;
 			| ^\\s*\\)
 		'


remove debugging

remove debugging

--- lib/git.coffee
+++ lib/git.coffee
@@ -144,8 +144,6 @@
     atom.project.getRepositories().filter((r) ->
       r?.repo.submoduleForPath path
     )[0]?.repo?.submoduleForPath path
-    debugger
-    repo

   # Returns the working directory for a git repo.
   # Will search for submodule first if currently


add template description

add template description

--- lib/scaffold/select-project-template-view.coffee
+++ lib/scaffold/select-project-template-view.coffee
@@ -39,10 +39,11 @@
 module.exports =
 class SelectTemplateView extends View
   @content: ->
-    @div =>
-      @h1 'Choose a template for your new project:'
+    @div id: 'project-template-chooser', =>
+      @h2 'Choose a template for your new project:'
       @div =>
         @subview 'gridView', new GridView()
+      @div 'Web Framework from best practice, MVC based on Backbone.js, structure code using Require.js', class: 'description'

   attachTo: (parentView)->
     parentView.append(this)


Slight changes in the exposure

Slight changes in the exposure

--- library/membrane/exposure.coffee
+++ library/membrane/exposure.coffee
@@ -23,6 +23,7 @@
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ###

+_ = require "lodash"
 asciify = require "asciify"
 connect = require "connect"
 logger = require "winston"
@@ -33,19 +34,13 @@
 http = require "http"
 util = require "util"

-_ = require "lodash"
-api = require "../nucleus/api"
-stubs = require "../nucleus/stubs"
-tools = require "../nucleus/tools"
-service = require "../nucleus/service"
-document = require "./document"
-skeleton = require "./skeleton"
+{Standard} = require "./skeleton"

 # This service exposes the entiry hierarchical structure of the
 # service documentation, as they scanned and found in the current
 # kernel instance. It exposes the data in a structured hierarchy
 # encoded with JSON. Please refer to the implementation for info.
-module.exports.ApiDoc = class ApiDoc extends skeleton.Standard
+module.exports.ApiDoc = class ApiDoc extends Standard

     # These invocations establish the parameters which are going
     # to be used for matching HTTP requests against this service.


Unify arg passing

Unify arg passing

--- library/membrane/validate.coffee
+++ library/membrane/validate.coffee
@@ -154,7 +154,7 @@
         @validateValues request.params, (failure, results) ->
             signature = [results, request, response, continuation]
             return @renderParamValidation signature... if failure
-            return continuation.bind(this) results
+            return continuation.bind(this) failure, results

 # This is an ABC service intended to be used only as a compund. It
 # provides a complete validation solution for request headers. The
@@ -208,4 +208,4 @@
         @validateValues request.headers, (failure, results) ->
             signature = [results, request, response, continuation]
             return @renderHeaderValidation signature... if failure
-            return continuation.bind(this) results
+            return continuation.bind(this) failure, results


update to ensure overrides go through

update to ensure overrides go through

--- lib/lt3.coffee
+++ lib/lt3.coffee
@@ -677,7 +677,6 @@
           package:
             id: pkg_id
             version: pkg_version
-          regions: {}
           settings:
             code_injection:
               header: ''
@@ -708,8 +707,6 @@
               mobile: 'slide'
               web: 'fade'
           slug: site_slug
-          style: {}
-          users: {}
         }
         setup_config = getCustomSetupConfig pkg_id, pkg_version

@@ -728,13 +725,21 @@

         # add self as admin
-        new_data.users[config.user._id] = 'admin'
-
-        #initialize if it doesn't exist
+
+
+        # initialize if it doesn't exist
         if not new_data.collections
-            new_data.collections={}
-
-
+          new_data.collections={}
+        if not new_data.regions
+          new_data.regions={}
+        if not new_data.style
+          new_data.style={}
+        if not new_data.users
+          new_data.users={}
+          new_data.users[config.user._id] = 'admin'
+
+
+
         # insert into database must happen first to get site _id
         db.get('sites').insert new_data, (err, site) ->
           throw err if err


fix a silliness

fix a silliness

--- src/kontrol/kontrol.coffee
+++ src/kontrol/kontrol.coffee
@@ -82,7 +82,7 @@
       changes.emit 'error', err
       return

-    [kite] = @kiteify [kiteDescriptor]
+    kite = @createKite kiteDescriptor

     eventName = @constructor.actions[action]
     changes.emit eventName, kite


Replace '&&' with 'and' for consistency.

--- src/Bacon.coffee
+++ src/Bacon.coffee
@@ -162,7 +162,7 @@
   new EventStream describe(Bacon, "fromArray", values), (sink) ->
     unsubd = false
     reply = Bacon.more
-    while (reply != Bacon.noMore) && !unsubd
+    while (reply != Bacon.noMore) and !unsubd
       if _.empty values
         sink(end())
         reply = Bacon.noMore
@@ -240,7 +240,7 @@
     if (isObservable(value))
       streams.push(value)
       funcs.push(applyStreamValue(key, streams.length - 1))
-    else if (value == Object(value) and typeof value != "function" && !(value instanceof RegExp) && !(value instanceof Date))
+    else if (value == Object(value) and typeof value != "function" and !(value instanceof RegExp) and !(value instanceof Date))
       pushContext = (key) -> (ctxStack) ->
         newContext = mkContext(value)
         setValue(ctxStack, key, newContext)
@@ -275,7 +275,7 @@
     Bacon.later(delay(context)).filter(false).concat(Bacon.once().flatMap(delayedRetry))

   withDescription(Bacon, "retry", options, source().flatMapError (e) ->
-    if isRetryable(e) && retries > 0
+    if isRetryable(e) and retries > 0
       retry(error: e, retriesDone: maxRetries - retries)
     else
       Bacon.once(new Error(e)))
@@ -381,7 +381,7 @@
     f = true if !f?
     convertArgsToFunction this, f, args, (f) ->
       withDescription(this, "endOnError", @withHandler (event) ->
-        if event.isError() && f(event.error)
+        if event.isError() and f(event.error)
           @push event
           @push end()
         else
@@ -491,7 +491,7 @@
               unsub = nop
       unsub = @subscribeInternal (event) ->
         if (event.hasValue())
-          if (initSent && event.isInitial())
+          if (initSent and event.isInitial())
             Bacon.more # init already sent, skip this one
           else
             sendInit() unless event.isInitial()
@@ -861,7 +861,7 @@
         event = event.toNext() if event.isInitial()
         sink event

-  and: (other) -> withDescription(this, "and", other, @combine(other, (x, y) -> x && y))
+  and: (other) -> withDescription(this, "and", other, @combine(other, (x, y) -> x and y))

   or:  (other) -> withDescription(this, "or", other, @combine(other, (x, y) -> x or y))

@@ -1011,7 +1011,7 @@
         # should bounce init value
         dispatchingId = UpdateBarrier.currentEventId()
         valId = currentValueRootId
-        if !ended && valId && dispatchingId && dispatchingId != valId
+        if !ended and valId and dispatchingId and dispatchingId != valId
           # when subscribing while already dispatching a value and this property hasn't been updated yet
           # we cannot bounce before this property is up to date.
           #console.log "bouncing with possibly stale value", event.value(), "root at", valId, "vs", dispatchingId


Handle Property initial value with Option type

--- src/Bacon.coffee
+++ src/Bacon.coffee
@@ -27,7 +27,6 @@
 Bacon.noMore = "veggies"

 Bacon.more = "moar bacon!"
-Bacon.none = {nothing: true}

 Bacon.never = => new EventStream (sink) =>
   => nop
@@ -466,19 +465,19 @@
       unsubBoth

   toProperty: (initValue) ->
-    initValue = Bacon.none if arguments.length == 0
+    initValue = Bacon.None if arguments.length == 0
     @scan(initValue, latter)

   scan: (seed, f) ->
-    acc = seed
+    acc = toOption(seed)
     f = toCombinator(f)

-    handleEvent = (event) ->
-      acc = f(acc, event.value) if event.hasValue()
-      @push event.apply(acc)
+    handleEvent = (event) ->
+      acc = new Some(f(acc.getOrElse(undefined), event.value)) if event.hasValue()
+      @push event.apply(acc.getOrElse(undefined))
     d = new Dispatcher(@subscribe, handleEvent)
     subscribe = (sink) ->
-      reply = sink initial(acc) if acc != Bacon.none
+      reply = acc.map((val) -> sink initial(val)).getOrElse Bacon.more
       d.subscribe(sink) unless reply == Bacon.noMore
     new Property(subscribe)

@@ -521,8 +520,8 @@
   constructor: (@subscribe) ->
     super()
     combine = (other, leftSink, rightSink) =>
-      myVal = Bacon.none
-      otherVal = Bacon.none
+      myVal = None
+      otherVal = None
       new Property (sink) =>
         unsubscribed = false
         unsubMe = nop
@@ -547,14 +546,14 @@
                 unsubBoth if reply == Bacon.noMore
                 reply
             else
-              setValue(event.value)
-              if (myVal != Bacon.none and otherVal != Bacon.none)
+              setValue(new Some(event.value))
+              if (myVal.isDefined and otherVal.isDefined)
                 if initialSent and event.isInitial()
                   # don't send duplicate Initial
                   Bacon.more
                 else
                   initialSent = true
-                  reply = thisSink(sink, event, myVal, otherVal)
+                  reply = thisSink(sink, event, myVal.value, otherVal.value)
                   unsubBoth if reply == Bacon.noMore
                   reply
               else
@@ -631,19 +630,19 @@
 class PropertyDispatcher extends Dispatcher
   constructor: (subscribe, handleEvent) ->
     super(subscribe, handleEvent)
-    current = Bacon.none
+    current = Bacon.None
     push = @push
     subscribe = @subscribe
     @push = (event) =>
       if event.hasValue()
-        current = event.value
+        current = new Some(event.value)
       push.apply(this, [event])
     @subscribe = (sink) =>
-      if @hasSubscribers() and current != Bacon.none
-        reply = sink initial(current)
-        if reply == Bacon.noMore
-          return nop
-      subscribe.apply(this, [sink])
+      reply = current.filter(@hasSubscribers).map((val) -> sink initial(val))
+      if reply.getOrElse(Bacon.more) == Bacon.noMore
+        nop
+      else
+        subscribe.apply(this, [sink])

 class Bus extends EventStream
   constructor: ->
@@ -684,6 +683,24 @@
       unsubAll()
       sink end() if sink?

+class Some
+  constructor: (@value) ->
+  getOrElse: -> @value
+  filter: (f) ->
+    if f @value
+      new Some(@value)
+    else
+      None
+  map: (f) ->
+    new Some(f @value)
+  isDefined: true
+
+None =
+  getOrElse: (value) -> value
+  filter: -> None
+  map: -> None
+  isDefined: false
+
 Bacon.EventStream = EventStream
 Bacon.Property = Property
 Bacon.Observable = Observable
@@ -692,6 +709,8 @@
 Bacon.Next = Next
 Bacon.End = End
 Bacon.Error = Error
+Bacon.None = None
+Bacon.Some = Some

 nop = ->
 latter = (_, x) -> x
@@ -767,5 +786,10 @@
       left[key](right)
   else
     assert "not a function or a field key: " + f, false
+toOption = (v) ->
+  if v instanceof Some || v == None
+    v
+  else
+    new Some(v)

 if define? and define.amd? then define? -> Bacon


Pending Tests for Transforms

Pending Tests for Transforms

--- test/bin.coffee
+++ test/bin.coffee
@@ -121,7 +121,14 @@
           'stdout is not matching as many times as expected'
         stderr.should.match /success/i
         done()
+
+    it 'should accept a transform bin'

+    it 'should limit the transform with an extension'
+
+    it 'should accept multiple transform bins'
+
+    it 'should limit multiple transforms by extensions'

   describe '(install)', ->
     bin       = null


generic death hook for later animation

generic death hook for later animation

--- src/Laser.coffee
+++ src/Laser.coffee
@@ -10,7 +10,7 @@
 		console.log 'you died by laser'

 		# restart the game state
-		@game.state.start('game')
+		app.death @
 		return true

 module.exports = Laser


fix topic

fix topic

--- app/assets/javascripts/rooms.coffee
+++ app/assets/javascripts/rooms.coffee
@@ -55,6 +55,24 @@
   change_topic = ->
     element = $('#drop1.change_topic.glyphicon.glyphicon-pencil')
     id = element.data('id')
+    if $("#change").val() is ""
+      $.bootstrapGrowl "You don't filed in requered fields",
+        type: "success"
+        offset:
+          from: "top"
+          amount: 50
+
+        align: "center"
+        width: 250
+        delay: 10000
+        allow_dismiss: true
+        stackup_spacing: 10
+
+      mymodal.hide()
+      $(".modal-backdrop").hide()
+      return
+
+    else
     $.ajax(
       type: "PUT"
       beforeSend: (xhr) ->


Allow tabs to be 'sticky' by adding the .with-history class

This leaves the default behaviour as having no history. We need the mixture
(e.g. no history on map edit tabs), so this is the cleanest way of adding
the functionality without needing dual declartions (ul.tabs, ul.tabs-with-history)
everywhere. Refs #62

--- app/assets/javascripts/ui.js.coffee
+++ app/assets/javascripts/ui.js.coffee
@@ -1,6 +1,7 @@
 jQuery ->
   # Tabs
-  $("ul.tabs").tabs "> div.panes > div"
+  $("ul.tabs").tabs("> div.panes > div")
+  $("ul.tabs.with-history").tabs("> div.panes > div", { history: true })

   # Scrollables
   $("div.scrollable.autoheight")


bugfix: deselect all wasn't functioning globally

--- app/assets/javascripts/works.coffee
+++ app/assets/javascripts/works.coffee
@@ -61,7 +61,7 @@
 )

 $(document).on("click", "span.unselect_all", (e)->
-  container_div = $(e.target).parents("form,.select_all_scope")[0]
+  container_div = $(e.target).parents(".select_all_scope, body")[0]
   inputs = container_div.querySelectorAll("input[name='selected_works[]']")
   for elem in inputs
     elem.checked = false


submit on enter in single line input if form is available

--- src/mentions-kinder.coffee
+++ src/mentions-kinder.coffee
@@ -55,6 +55,8 @@
     # don't allow newline in singleline input
     if charCode == KEY.RETURN && !@multiline
       e.preventDefault()
+      if @submitOnEnter
+        @$form.submit()

   handleKeyup: (e)=>
     if @isAutocompleting()
@@ -280,15 +282,19 @@
     undefined

   _setupEvents: ->
+    # editable events
     @$editable.bind 'keypress', @handleInput
     @$editable.bind 'keyup', @handleKeyup
     @$editable.bind 'paste', @handlePaste
     @$editable.bind 'focus blur', @handlePlaceholder
-
+    # input events
     @$originalInput.bind 'change', @deserializeFromInput
+    # form related events
     if form = @$originalInput.get(0).form
-      $(form).on('reset', @handleReset)
-      $(form).on('reset', @handlePlaceholder)
+      @$form = $(form)
+      @submitOnEnter = true if !@multiline
+      @$form.on('reset', @handleReset)
+      @$form.on('reset', @handlePlaceholder)

   _setCaretToEndOf: (node)->
     selection = rangy.getSelection()


package: added buildPackage and buildPackageToFile methods

--- src/_SimQ.coffee
+++ src/_SimQ.coffee
@@ -44,12 +44,35 @@
 		return @

+	buildPackage: (name) ->
+		if !@hasPackage(name)
+			throw new Error 'Package ' + name + ' is not registered.'
+
+		return (new Builder(@packages[name])).build()
+
+
+	buildPackageToFile: (name, file) ->
+		if !@hasPackage(name)
+			throw new Error 'Package ' + name + ' is not registered.'
+
+		deferred = Q.defer()
+
+		@buildPackage(name).then( (data) ->
+			fs.writeFileSync(file, data)
+			deferred.resolve(data)
+		).fail( (err) ->
+			deferred.reject(err)
+		)
+
+		return deferred.promise
+
+
 	build: ->
 		deferred = Q.defer()

 		result = []
 		for name, pckg of @packages
-			result.push((new Builder(pckg)).build())
+			result.push(@buildPackage(name))

 		Q.all(result).then( (data) =>
 			result = {}
@@ -69,14 +92,21 @@
 	buildToFiles: ->
 		deferred = Q.defer()

-		@build().then( (packages) =>
-			for name, pckg of packages
-				if @packages[name].application != null
-					fs.writeFileSync(@packages[name].application, pckg)
+		result = []
+		for name, pckg of @packages
+			if pckg.application != null
+				result.push(@buildPackageToFile(name, pckg.application))

-			deferred.resolve(packages)
+		Q.all(result).then( (data) =>
+			result = {}
+			count = 0
+			for name, pckg of @packages
+				result[name] = data[count]
+				count++
+
+			deferred.resolve(result)
 		).fail( (err) ->
-			deffered.reject(err)
+			deferred.reject(err)
 		)

 		return deferred.promise


Update comment.

Update comment.

--- app/client/js/facebook/store.coffee
+++ app/client/js/facebook/store.coffee
@@ -6,9 +6,11 @@
 class app.facebook.Store

   ###*
-    Note FB.logout is not used, because it logout user out of Facebook entirely.
-    Also FB.getLoginStatus is not used, because loginStatus is handled by app.
-    User login status is persisted in localStorage via usersStore.
+    FB account is used for login. Note FB.logout is not used, because it logout
+    user out of Facebook entirely, which is not what we want.FB.getLoginStatus
+    isn't used too, because loginStatus is handled by app itself. After login,
+    login status is persisted in localStorage via usersStore and sent to server.
+    Server issues session cookie via FB confirmed identity.
     @param {app.Dispatcher} dispatcher
     @constructor
   ###


fix issue #4749, reload wiki after delete

--- app/coffee/modules/wiki/main.coffee
+++ app/coffee/modules/wiki/main.coffee
@@ -150,6 +150,7 @@
                 ctx = {project: @scope.projectSlug}
                 @location.path(@navUrls.resolve("project-wiki", ctx))
                 @confirm.notify("success")
+                @.loadWiki()

             onError = =>
                 askResponse.finish(false)


Rollback matching logic

Rollback matching logic

--- src/alias.coffee
+++ src/alias.coffee
@@ -16,16 +16,12 @@
   robot.receive = (msg)->
     table = robot.brain.get(ALIAS_TABLE_KEY) || {}
     orgText = msg.text?.trim()
-    if /^hubot\salias/.test orgText
-      # Skip the check
-    else if /^hubot(\s)(.*)$/.test orgText
+
+    if /hubot(\s)([^\s]*)(.*)$/.test orgText
       sp = RegExp.$1
-      text = RegExp.$2
-      for regexp, value of table
-        replaced = text.replace(new RegExp("^" + regexp + "\\b"), value)
-        if text != replaced
-          msg.text = "hubot#{sp}#{replaced}"
-          break
+      action = RegExp.$2
+      rest = RegExp.$3
+      msg.text = "hubot#{sp}#{table[action] || action}#{rest}" if action != 'alias'
     console.log "Change \"#{orgText}\" as \"#{msg.text}\"" if orgText != msg.text

     receiveOrg.bind(robot)(msg)


bug fix subscribing to tools

bug fix subscribing to tools

--- app/controllers/DataSettings.coffee
+++ app/controllers/DataSettings.coffee
@@ -55,7 +55,8 @@
         params = @params.val()

     dataSource = Source[source]
-    @bindTool dataSource, params
+    source = dataSource if @source is 'api'
+    @bindTool @source, source, params

   setBindOptions: (source, params='') =>
     @bindOptions = {
@@ -67,7 +68,7 @@
     else
       @bindOptions = _.extend @bindOptions, {type: 'channel', process: @process}

-  bindTool: (source, params='') =>
+  bindTool: (source_type, source, params='') =>
     @setBindOptions source, params
     if @bindOptions.type is 'api'
       @getDataSource source, params


fixes #65

fixes #65

--- src/modules/toolbar.coffee
+++ src/modules/toolbar.coffee
@@ -2,6 +2,7 @@
 ScribeKeyboard    = require('../keyboard')
 ScribeRange       = require('../range')
 ScribeLinkTooltip = require('./link-tooltip')
+ScribeUtils       = require('../utils')

 _findInput = (format) ->
@@ -24,6 +25,7 @@
         range = @editor.getSelection()
         if range
           @editor.root.focus()
+          @editor.setSelection(range) if ScribeUtils.isIE(9)    # Not sure this can't be done for all browsers, but breaks principle of messing with selection as little as possible
           range.format(format, value, { source: 'user' })
         activeFormats = {}
         activeFormats[format] = value


Revert "link-tooltip: allow for link tooltip to be positioned outside the bounds of the container"

This reverts commit 04c7c277bce2e879c32aa2cdc2df60f4bd82bd5c.

--- src/modules/tooltip.coffee
+++ src/modules/tooltip.coffee
@@ -42,17 +42,17 @@
     if reference?
       # Place tooltip under reference centered
       # reference might be selection range so must use getBoundingClientRect()
-      tooltipBounds = @container.getBoundingClientRect()
       referenceBounds = reference.getBoundingClientRect()
       parentBounds = @quill.container.getBoundingClientRect()
       offsetLeft = referenceBounds.left - parentBounds.left
       offsetTop = referenceBounds.top - parentBounds.top
-      left = offsetLeft + referenceBounds.width/2 - tooltipBounds.width/2
+      offsetBottom = referenceBounds.bottom - parentBounds.bottom
+      left = offsetLeft + referenceBounds.width/2 - @container.offsetWidth/2
       top = offsetTop + referenceBounds.height + @options.offset
-      if top + tooltipBounds.height > parentBounds.height
-        top = offsetTop - tooltipBounds.height - @options.offset
-      left = Math.max(-parentBounds.left, Math.min(left, parentBounds.width - tooltipBounds.width))
-      top = Math.max(-parentBounds.top, Math.min(top, parentBounds.height - tooltipBounds.height))
+      if top + @container.offsetHeight > @quill.container.offsetHeight
+        top = offsetTop - @container.offsetHeight - @options.offset
+      left = Math.max(0, Math.min(left, @quill.container.offsetWidth - @container.offsetWidth))
+      top = Math.max(0, Math.min(top, @quill.container.offsetHeight - @container.offsetHeight))
     else
       # Place tooltip in middle of editor viewport
       left = @quill.container.offsetWidth/2 - @container.offsetWidth/2


Remove dblclick event handler on taxon tree

This wasn't working for me in either chrome or firefox, and is
unnecessary as rename is available in the right click menu.

--- backend/app/assets/javascripts/spree/backend/taxonomy.js.coffee
+++ backend/app/assets/javascripts/spree/backend/taxonomy.js.coffee
@@ -119,9 +119,6 @@
           .bind "loaded.jstree", ->
             $(this).jstree("core").toggle_node($('.jstree-icon').first())

-    $("#taxonomy_tree a").on "dblclick", (e) ->
-      $("#taxonomy_tree").jstree("rename", this)
-
     # surpress form submit on enter/return
     $(document).keypress (e) ->
       if e.keyCode == 13


Fixing erroneous whitespace fix in generated JS

--- nodes.coffee
+++ nodes.coffee
@@ -351,7 +351,7 @@
         if assigns
           fragments.push @makeCode ",\n#{@tab + TAB}" if declars
           fragments.push @makeCode (scope.assignedVariables().join ",\n#{@tab + TAB}")
-        fragments.push @makeCode ';\n\n'
+        fragments.push @makeCode ";\n#{if @spaced then '\n' else ''}"
     fragments.concat post

   # Wrap up the given nodes as a **Block**, unless it already happens


removing holmsand's cleanup

removing holmsand's cleanup

--- nodes.coffee
+++ nodes.coffee
@@ -1118,13 +1118,10 @@
     var_part:       ''
     body:           Expressions.wrap([@body])
     if range
-      index_var:    scope.free_variable()
       source_part:  source.compile_variables o
       for_part:     source.compile merge o, {index: ivar, step: @step}
-      for_part:     "$index_var = 0, $for_part, $index_var++"
     else
       svar:         scope.free_variable()
-      index_var:    null
       source_part:  "$svar = ${ @source.compile(o) };\n$@tab"
       if @pattern
         var_part:   new AssignNode(@name, literal("$svar[$ivar]")).compile(merge o, {indent: @idt(1), top: true}) + "\n"


changed uses of the `slice` method to CS slices in `nodes.coffee`

--- nodes.coffee
+++ nodes.coffee
@@ -388,7 +388,7 @@
     name = last @properties
     if @properties.length < 2 and not @base.isComplex() and not name?.isComplex()
       return [this, this]  # `a` `a.b`
-    base = new Value @base, @properties.slice 0, -1
+    base = new Value @base, @properties[...-1]
     if base.isComplex()  # `a().b`
       bref = new Literal o.scope.freeVariable 'base'
       base = new Value new Parens new Assign bref, base
@@ -420,8 +420,8 @@
         return ifn
       for prop, i in @properties when prop.soak
         prop.soak = off
-        fst = new Value @base, @properties.slice 0, i
-        snd = new Value @base, @properties.slice i
+        fst = new Value @base, @properties[...i]
+        snd = new Value @base, @properties[i..]
         if fst.isComplex()
           ref = new Literal o.scope.freeVariable 'ref'
           fst = new Parens new Assign ref, fst
@@ -839,7 +839,7 @@
   # Merge the properties from a top-level object as prototypal properties
   # on the class.
   addProperties: (node, name, o) ->
-    props = node.base.properties.slice 0
+    props = node.base.properties[0..]
     exprs = while assign = props.shift()
       if assign instanceof Assign
         base = assign.variable.base
@@ -1028,7 +1028,7 @@
   compileConditional: (o) ->
     [left, rite] = @variable.cacheReference o
     if "?" in @context then o.isExistentialEquals = true
-    new Op(@context.slice(0, -1), left, new Assign(rite, @value, '=') ).compile o
+    new Op(@context[0...-1], left, new Assign(rite, @value, '=') ).compile o

   # Compile the assignment from an array splice literal, using JavaScript's
   # `Array#splice` method.
@@ -1173,14 +1173,14 @@
       code = list[0].compile o, LEVEL_LIST
       return code if apply
       return "#{ utility 'slice' }.call(#{code})"
-    args = list.slice index
+    args = list[index..]
     for node, i in args
       code = node.compile o, LEVEL_LIST
       args[i] = if node instanceof Splat
       then "#{ utility 'slice' }.call(#{code})"
       else "[#{code}]"
-    return args[0] + ".concat(#{ args.slice(1).join ', ' })" if index is 0
-    base = (node.compile o, LEVEL_LIST for node in list.slice 0, index)
+    return args[0] + ".concat(#{ args[1..].join ', ' })" if index is 0
+    base = (node.compile o, LEVEL_LIST for node in list[0...index])
     "[#{ base.join ', ' }].concat(#{ args.join ', ' })"

 #### While


disallow index mentions for range loops.

--- nodes.coffee
+++ nodes.coffee
@@ -1380,7 +1380,8 @@
     throw SyntaxError 'index cannot be a pattern matching expression' if @index instanceof Value
     @range   = @source instanceof Value and @source.base instanceof Range and not @source.properties.length
     @pattern = @name instanceof Value
-    throw SyntaxError 'cannot pattern match a range loop' if @range and @pattern
+    throw SyntaxError 'indexes do not apply to range loops' if @range and @index
+    throw SyntaxError 'cannot pattern match over range loops' if @range and @pattern
     @returns = false

   children: ['body', 'source', 'guard', 'step']


satyr commit b2cf91 ... no more @tags

satyr commit b2cf91 ... no more @tags

--- nodes.coffee
+++ nodes.coffee
@@ -27,8 +27,6 @@
 # being requested by the surrounding function), information about the current
 # scope, and indentation level.
 exports.Base = class Base
-
-  constructor: -> @tags = {}

   # Common logic for determining whether to wrap this node in a closure before
   # compiling it, or to compile directly. We need to wrap if this node is a
@@ -166,7 +164,6 @@
   isStatement: YES

   constructor: (nodes) ->
-    super()
     @expressions = compact flatten nodes or []

   # Tack an expression on to the end of this expression list.
@@ -234,7 +231,7 @@
   compileExpression: (node, o) ->
     node = node.unwrapAll()
     node = node.unfoldSoak(o) or node
-    node.tags.front = on
+    node.front = yes
     o.level = LEVEL_TOP
     code    = node.compile o
     if node.isStatement o then code else @tab + code + ';'
@@ -252,7 +249,7 @@
 # `true`, `false`, `null`...
 exports.Literal = class Literal extends Base

-  constructor: (@value) -> super()
+  constructor: (@value) ->

   makeReturn: -> if @isStatement() then this else super()

@@ -281,7 +278,7 @@
   isStatement    : YES
   isPureStatement: YES

-  constructor: (@expression) -> super()
+  constructor: (@expression) ->

   makeReturn: THIS

@@ -306,7 +303,7 @@
     return base if not props and base instanceof Value
     @base       = base
     @properties = props or []
-    @tags       = if tag then {(tag): on} else {}
+    @[tag]      = true if tag

   # Add a property access to the list.
   push: (prop) ->
@@ -358,7 +355,7 @@
   # operators `?.` interspersed. Then we have to take care not to accidentally
   # evaluate anything twice when building the soak chain.
   compileNode: (o) ->
-    @base.tags.front = @tags.front
+    @base.front = @front
     props = @properties
     code  = @base.compile o, if props.length then LEVEL_ACCESS else null
     code  = "(#{code})" if props[0] instanceof Accessor and @isSimpleNumber()
@@ -390,7 +387,7 @@
   isPureStatement: YES
   isStatement:     YES

-  constructor: (@comment) -> super()
+  constructor: (@comment) ->

   makeReturn: THIS

@@ -405,7 +402,6 @@
   children: ['variable', 'args']

   constructor: (variable, @args = [], @soak) ->
-    super()
     @isNew    = false
     @isSuper  = variable is 'super'
     @variable = if @isSuper then null else variable
@@ -460,7 +456,7 @@

   # Compile a vanilla function call.
   compileNode: (o) ->
-    @variable?.tags.front = @tags.front
+    @variable?.front = @front
     for arg in @args when arg instanceof Splat
       return @compileSplat o
     args = (arg.compile o, LEVEL_LIST for arg in @args).join ', '
@@ -508,7 +504,7 @@

   children: ['child', 'parent']

-  constructor: (@child, @parent) -> super()
+  constructor: (@child, @parent) ->

   # Hooks one constructor into another's prototype chain.
   compile: (o) ->
@@ -523,7 +519,6 @@
   children: ['name']

   constructor: (@name, tag) ->
-    super()
     @proto = if tag is 'proto' then '.prototype' else ''
     @soak  = tag is 'soak'

@@ -540,7 +535,7 @@

   children: ['index']

-  constructor: (@index) -> super()
+  constructor: (@index) ->

   compile: (o) ->
     (if @proto then '.prototype' else '') + "[#{ @index.compile o, LEVEL_PAREN }]"
@@ -555,7 +550,6 @@
   children: ['properties']

   constructor: (props) ->
-    super()
     @objects = @properties = props or []

   compileNode: (o) ->
@@ -573,7 +567,7 @@
       else
         ',\n'
       indent = if prop instanceof Comment then '' else idt
-      if prop instanceof Value and prop.tags.this
+      if prop instanceof Value and prop.this
         prop = new Assign prop.properties[0].name, prop, 'object'
       else if prop not instanceof Assign and prop not instanceof Comment
         prop = new Assign prop, prop, 'object'
@@ -581,7 +575,7 @@
     props = props.join ''
     obj   = "{#{ props and '\n' + props + '\n' + @tab }}"
     return @compileDynamic o, obj, rest if rest
-    if @tags.front then "(#{obj})" else obj
+    if @front then "(#{obj})" else obj

   compileDynamic: (o, code, props) ->
     code = "#{ oref = o.scope.freeVariable 'obj' } = #{code}, "
@@ -617,7 +611,6 @@
   children: ['objects']

   constructor: (objs) ->
-    super()
     @objects = objs or []

   compileNode: (o) ->
@@ -655,10 +648,7 @@

   # Initialize a **Class** with its name, an optional superclass, and a
   # list of prototype property assignments.
-  constructor: (@variable, @parent, props) ->
-    super()
-    @properties = props or []
-    @returns    = false
+  constructor: (@variable, @parent, @properties = []) ->

   makeReturn: ->
     @returns = true
@@ -739,7 +729,7 @@

   children: ['variable', 'value']

-  constructor: (@variable, @value, @context) -> super()
+  constructor: (@variable, @value, @context) ->

   assigns: (name) ->
     @[if @context is 'object' then 'value' else 'variable'].assigns name
@@ -786,7 +776,7 @@
           [obj, idx] = new Value(obj.unwrapAll()).cacheReference o
         else
           idx = if isObject
-            if obj.tags.this then obj.properties[0].name else obj
+            if obj.this then obj.properties[0].name else obj
           else
             new Literal 0
       acc   = IDENTIFIER.test idx.unwrap().value or 0
@@ -811,7 +801,7 @@
           if obj.base instanceof Parens
             [obj, idx] = new Value(obj.unwrapAll()).cacheReference o
           else
-            idx = if obj.tags.this then obj.properties[0].name else obj
+            idx = if obj.this then obj.properties[0].name else obj
       if not splat and obj instanceof Splat
         val = "#{olen} <= #{vvar}.length ? #{ utility 'slice' }.call(#{vvar}, #{i}"
         if rest = olen - i - 1
@@ -854,7 +844,6 @@
   children: ['params', 'body']

   constructor: (@params = [], @body = new Expressions, tag) ->
-    super()
     @bound   = tag is 'boundfunc'
     @context = 'this' if @bound

@@ -907,7 +896,7 @@
     func = "#{open}#{ vars.join ', ' }) {#{code}#{close}"
     scope.endLevel()
     return "#{ utility 'bind' }(#{func}, #{@context})" if @bound
-    if @tags.front then "(#{func})" else func
+    if @front then "(#{func})" else func

   # Short-circuit `traverseChildren` method to prevent it from crossing scope boundaries
   # unless `crossScope` is `true`.
@@ -923,7 +912,6 @@
   children: ['name', 'value']

   constructor: (@name, @value, @splat) ->
-    super()

   compile: (o) -> @name.compile o, LEVEL_LIST

@@ -947,7 +935,6 @@
   isAssignable: YES

   constructor: (name) ->
-    super()
     @name = if name.compile then name else new Literal name

   assigns: (name) -> @name.assigns name
@@ -984,10 +971,9 @@

   isStatement: YES

-  constructor: (condition, opts) ->
-    super()
-    @condition = if opts?.invert then condition.invert() else condition
-    @guard     = opts?.guard
+  constructor: (condition, options) ->
+    @condition = if options?.invert then condition.invert() else condition
+    @guard     = options?.guard

   addBody: (body) ->
     @body = body
@@ -1043,7 +1029,6 @@
     if op is 'new'
       return first.newInstance() if first instanceof Call
       first = new Parens first   if first instanceof Code and first.bound
-    super()
     @operator = @CONVERSIONS[op] or op
     @first    = first
     @second   = second
@@ -1071,7 +1056,7 @@
     return @compileUnary     o if @isUnary()
     return @compileChain     o if @isChainable() and @first.isChainable()
     return @compileExistence o if @operator is '?'
-    @first.tags.front = @tags.front
+    @first.front = @front
     "#{ @first.compile o, LEVEL_OP } #{@operator} #{ @second.compile o, LEVEL_OP }"

   # Mimic Python's chained comparisons when multiple comparison operators are
@@ -1111,7 +1096,7 @@

   children: ['object', 'array']

-  constructor: (@object, @array) -> super()
+  constructor: (@object, @array) ->

   invert: ->
     @negated = not @negated
@@ -1151,7 +1136,7 @@

   isStatement: YES

-  constructor: (@attempt, @error, @recovery, @ensure) -> super()
+  constructor: (@attempt, @error, @recovery, @ensure) ->

   makeReturn: ->
     @attempt  = @attempt .makeReturn() if @attempt
@@ -1182,7 +1167,7 @@

   isStatement: YES

-  constructor: (@expression) -> super()
+  constructor: (@expression) ->

   # A **Throw** is already a return, of sorts...
   makeReturn: THIS
@@ -1198,7 +1183,7 @@

   children: ['expression']

-  constructor: (@expression) -> super()
+  constructor: (@expression) ->

   compileNode: (o) ->
     code = @expression.compile o
@@ -1219,7 +1204,7 @@

   children: ['expression']

-  constructor: (@expression) -> super()
+  constructor: (@expression) ->

   unwrap    : -> @expression
   isComplex : -> @expression.isComplex()
@@ -1228,7 +1213,7 @@
   compileNode: (o) ->
     expr = @expression
     if expr instanceof Value and expr.isAtomic()
-      expr.tags.front = @tags.front
+      expr.front = @front
       return expr.compile o
     bare = o.level < LEVEL_OP and (expr instanceof Op or expr instanceof Call)
     code = expr.compile o, LEVEL_PAREN
@@ -1252,7 +1237,6 @@
   constructor: (@body, head) ->
     if head.index instanceof Value
       throw SyntaxError 'index cannot be a pattern matching expression'
-    super()
     extend this, head
     @step  or= new Literal 1 unless @object
     @pattern = @name instanceof Value
@@ -1341,7 +1325,7 @@

   isStatement: YES

-  constructor: (@subject, @cases, @otherwise) -> super()
+  constructor: (@subject, @cases, @otherwise) ->

   makeReturn: ->
     pair[1].makeReturn() for pair in @cases
@@ -1375,11 +1359,11 @@

   children: ['condition', 'body', 'elseBody']

-  constructor: (condition, @body, @tags = {}) ->
-    @condition = if @tags.invert then condition.invert() else condition
+  constructor: (condition, @body, options = {}) ->
+    @condition = if options.invert then condition.invert() else condition
     @elseBody  = null
     @isChain   = false
-    {@soak}    = @tags
+    {@soak}    = options

   bodyNode: -> @body?.unwrap()
   elseBodyNode: -> @elseBody?.unwrap()


search export captured. Now "just" the diffs

--- chrome/content/zotero-better-bibtex/zotero-better-bibtex.coffee
+++ chrome/content/zotero-better-bibtex/zotero-better-bibtex.coffee
@@ -462,6 +462,10 @@
       progressWin.changeHeadline('Auto-export')

       switch
+        when @_saved_search # search export, already converted to its corresponding items above
+          progressWin.addLines(["Saved search #{@_saved_search.name} set up for auto-export"])
+          collection = "search:#{@_saved_search.id}"
+
         when @_group # group export, already converted to its corresponding items above
           progressWin.addLines(["Group #{@_group.name} set up for auto-export"])
           collection = "library:#{@_group.libraryID}"
@@ -475,7 +479,7 @@
           collection = 'library'

         else
-          progressWin.addLines(['Auto-export only supported for groups, collections and libraries'])
+          progressWin.addLines(['Auto-export only supported for searches, groups, collections and libraries'])
           collection = null

       progressWin.show()


prep for removal of __exposedProps__ (grmbl stupid signing enforcement), undoing damage done to Function by recoll-firefox

--- chrome/content/zotero-better-bibtex/zotero-better-bibtex.coffee
+++ chrome/content/zotero-better-bibtex/zotero-better-bibtex.coffee
@@ -1,6 +1,12 @@
 Components.utils.import('resource://gre/modules/Services.jsm')
 Components.utils.import('resource://gre/modules/AddonManager.jsm')
 Components.utils.import('resource://zotero/config.js')
+
+# not cool, recoll-firefox-extension
+if 'recoll_bind' in Object.keys(Function::)
+  recoll_bind = Function::recoll_bind
+  delete Function::recoll_bind
+  Object.defineProperty(Function::, 'recoll_bind', { value: recoll_bind, enumerable: false })

 Zotero.BetterBibTeX = {
   serializer: Components.classes['@mozilla.org/xmlextras/xmlserializer;1'].createInstance(Components.interfaces.nsIDOMSerializer)


Prevent space bar from scrolling the page in PlayGameDevLevelView (#5055)

In PlayGameDevLevelView, Space bar can be used as a control in the game, so prevent its default behavior of scrolling down the page

--- app/views/play/level/PlayGameDevLevelView.coffee
+++ app/views/play/level/PlayGameDevLevelView.coffee
@@ -45,6 +45,11 @@
       creatorString: ''
       isOwner: false
     })
+
+    $(window).keydown (event) ->
+      # prevent space from scrolling on the page since it can be used as a control in the game.
+      if (event.keyCode == 32 && event.target == document.body)
+        event.preventDefault()

     if utils.getQueryVariable 'dev'
       @supermodel.shouldSaveBackups = (model) ->  # Make sure to load possibly changed things from localStorage.
@@ -239,4 +244,5 @@
     @goalManager?.destroy()
     @scriptManager?.destroy()
     delete window.world # not sure where this is set, but this is one way to clean it up
+    $(window).off("keydown")
     super()


Fix deprecation warning and fix indentation

--- keymaps/python-isort.cson
+++ keymaps/python-isort.cson
@@ -1,4 +1,4 @@
 # For more detailed documentation see
 # https://atom.io/docs/latest/advanced/keymaps
-'.editor.python':
-    'ctrl-alt-s': 'python-isort:sortImports'
+'atom-text-editor[data-grammar="source python"]':
+  'ctrl-alt-s': 'python-isort:sortImports'


nfindercontroller: reset work for only active machine

--- client/finder/lib/filetree/controllers/nfindercontroller.coffee
+++ client/finder/lib/filetree/controllers/nfindercontroller.coffee
@@ -107,6 +107,11 @@

   mountMachine: (machine, options = {}) ->
+
+    { frontApp } = kd.singletons['appManager']
+    machineToMount = frontApp.mountedMachine
+    return  unless machine.uid is machineToMount.uid
+
     options.fetchContent ?= yes

     unless machine.status.state is Machine.State.Running


Unfortunately, delete tests are still failing sporadically in Jenkins.

--- cms/static/coffee/spec/views/overview_spec.coffee
+++ cms/static/coffee/spec/views/overview_spec.coffee
@@ -97,20 +97,22 @@
             $('a.save-button').click()
             expect(@notificationSpy).toHaveBeenCalled()

-        it "should delete model when delete is clicked", ->
-            $('a.delete-section-button').click()
-            $('a.action-primary').click()
-            expect(@requests[0].url).toEqual('/delete_item')
+        # Fails sporadically in Jenkins.
+#        it "should delete model when delete is clicked", ->
+#            $('a.delete-section-button').click()
+#            $('a.action-primary').click()
+#            expect(@requests[0].url).toEqual('/delete_item')

         it "should not delete model when cancel is clicked", ->
             $('a.delete-section-button').click()
             $('a.action-secondary').click()
             expect(@requests.length).toEqual(0)

-        it "should show a confirmation on delete", ->
-            $('a.delete-section-button').click()
-            $('a.action-primary').click()
-            expect(@notificationSpy).toHaveBeenCalled()
+        # Fails sporadically in Jenkins.
+#        it "should show a confirmation on delete", ->
+#            $('a.delete-section-button').click()
+#            $('a.action-primary').click()
+#            expect(@notificationSpy).toHaveBeenCalled()

         describe "findDestination", ->
             it "correctly finds the drop target of a drag", ->


module doc improvements

module doc improvements

doc argument is optional. doc function takes complete arg

--- src/modules.coffee
+++ src/modules.coffee
@@ -8,27 +8,37 @@
     module_settings = settings.with_prefix module_name
     context_fns = {}

-    cmd = (name, doc, wrapped) ->
-      fn name, doc, wrapped, wrapped
+    doc = (name, summary, complete) ->
+      Documentation.register_documentation [module_name, name], {summary, complete}

-    fn = (name, doc, fn, cmd_fn) ->
-      Documentation.register_documentation [module_name, name], summary: doc
+    optional_doc_fn = (f) ->
+      (args...) ->
+        if _.isString args[1]
+          [name, summary] = args
+          doc name, summary
+          args.splice 1, 1
+        f args...
+
+    cmd = optional_doc_fn (name, wrapped) ->
+      fn name, wrapped, wrapped
+
+    fn = optional_doc_fn (name, f, cmd_f) ->
       result =
         module_name: module_name
-        fn: fn
-        cmd_fn: cmd_fn
+        fn: f
+        cmd_fn: cmd_f
         name: name

       context_fns[name] = result

     # TODO does this belong here?
-    component_fn = (name, doc, f) ->
-      fn name, doc, -> @add_component f.apply @, arguments
+    component_fn = optional_doc_fn (name, f) ->
+      fn name, -> @add_component f.apply @, arguments

-    component_cmd= (name, doc, f) ->
-      cmd name, doc, -> @add_component f.apply @, arguments
+    component_cmd = optional_doc_fn (name, f) ->
+      cmd name, -> @add_component f.apply @, arguments

-    mod = {cmd, fn, component_cmd, component_fn, context_fns, settings: module_settings}
+    mod = {doc, cmd, fn, component_cmd, component_fn, context_fns, settings: module_settings}
     if definition_fn?
       _.extend {context_fns, settings}, definition_fn mod
     else


Wider minWidth for marks

Wider minWidth for marks

--- app/lib/mark.coffee
+++ app/lib/mark.coffee
@@ -34,7 +34,7 @@

   toPixels: (dataPoint) -> ((parseFloat(dataPoint) - parseFloat(@xMin)) / (parseFloat(@xMax) - parseFloat(@xMin))) * (parseFloat(@canvas.width)-parseFloat(@leftPadding))

-  minWidth: -> 10
+  minWidth: -> 15

   maxWidth: -> 200 * @canvasGraph.scale


Observe autoIndentJSX config for already existing editors.

--- lib/auto-indent.coffee
+++ lib/auto-indent.coffee
@@ -50,6 +50,9 @@
     @eslintIndentOptions = @getIndentOptions()
     @templateDepth = 0 # track depth of any embedded back-tick templates

+    # Observe autoIndentJSX for existing editors
+    @disposables.add atom.config.observe 'language-babel.autoIndentJSX',
+      (value) => @autoJsx = value

     @disposables.add atom.commands.add 'atom-text-editor',
       'language-babel:auto-indent-jsx-on': (event) =>


fixing savedProps regression

fixing savedProps regression

--- src/natives.coffee
+++ src/natives.coffee
@@ -574,7 +574,10 @@
   sun:
     misc:
       VM: [
-        o 'initialize()V', (rs, _this) ->
+        o 'initialize()V', (rs) ->
+            vm_cls = rs.class_lookup c2t 'sun/misc/VM'
+            # this only applies to Java 7
+            return unless vm_cls.major_version >= 51
             # hack! make savedProps refer to the system props
             rs.push rs.static_get {class:'java/lang/System',name:'props'}
             rs.static_put {class:'sun/misc/VM',name:'savedProps'}


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/color.coffee
+++ src/color.coffee
@@ -186,8 +186,6 @@

       grayscale: ->
         hsl = self.toHsl()
-
-        log hsl

         g = hsl[2] * 255


Delete opinion ratio table

Delete opinion ratio table

--- core/app/backbone/views/facts/react_fact_opinionate_area.coffee
+++ core/app/backbone/views/facts/react_fact_opinionate_area.coffee
@@ -66,24 +66,6 @@
         ReactSigninPopover
           ref: 'signinPopover'

-
-FactOpinionTallyChart = React.createClass
-  displayName: 'FactOpinionTallyChart'
-
-  render: ->
-    laplace_smoothing_offset = 0.2
-    total = @props.believes + @props.disbelieves + 2*laplace_smoothing_offset
-    believe_percentage = 100 * (@props.believes + laplace_smoothing_offset) / total
-    disbelieve_percentage = 100 * (@props.disbelieves + laplace_smoothing_offset) / total
-
-    _table ["fact-opinion-tally-chart"],
-      _tbody [],
-        _tr [],
-          _td ["fact-opinion-tally-chart-believers"
-               style: {width: "#{believe_percentage}%"}]
-          _td ["fact-opinion-tally-chart-disbelievers"
-               style: {width: "#{disbelieve_percentage}%"}]
-
 FactOpinionatorsTable = React.createBackboneClass
   displayName: 'FactOpinionatorsTable'
   changeOptions: 'add remove reset sort' + ' change'
@@ -98,10 +80,6 @@
       _table ["fact-opinionators-table-table"],
         _tr [],
           _td ["fact-opinionators-table-believes"], opinionTally.believes
-          _td [],
-            FactOpinionTallyChart
-              believes: opinionTally.believes
-              disbelieves: opinionTally.disbelieves
           _td ["fact-opinionators-table-disbelieves"], opinionTally.disbelieves

 window.ReactOpinionateArea = React.createBackboneClass


Combined Macro snippets, Added newlines between snippets for readability

--- snippets/language-sqf.cson
+++ snippets/language-sqf.cson
@@ -1,3 +1,4 @@
+# Code
 '.source.sqf':
   # BI Commands - Conditional Structures
   'If Then statement':
@@ -9,6 +10,7 @@
     """
     'description': 'Conditional if statement'
     'descriptionMoreURL': 'https://community.bistudio.com/wiki/if'
+
   'If Then Else statement':
     'prefix': 'if_then_else'
     'body': """
@@ -20,12 +22,14 @@
     """
     'description': 'Conditional if-else statement'
     'descriptionMoreURL': 'https://community.bistudio.com/wiki/else'
+
   'If Then Else assignment':
     'prefix': 'if_then_else_assign'
     'body': """
       ${1:VARIABLE} = if (${2:CONDITION}) then {${3:ASSIGNMENT_TRUE}} else {${4:ASSIGNMENT_FALSE}};
     """
     'description': 'Conditional if-else assignment'
+
   'Switch statement':
     'prefix': 'switch'
     'body': """
@@ -35,6 +39,7 @@
     """
     'description': 'Conditional switch statement'
     'descriptionMoreURL': 'https://community.bistudio.com/wiki/switch_do'
+
   'Case block of Switch':
     'prefix': 'case_switch'
     'body': """
@@ -44,6 +49,7 @@
     """
     'description': 'Case block inside switch statement'
     'descriptionMoreURL': 'https://community.bistudio.com/wiki/case'
+
   'Default block of Switch':
     'prefix': 'default_switch'
     'body': """
@@ -53,6 +59,7 @@
     """
     'description': 'Default block inside switch statement'
     'descriptionMoreURL': 'https://community.bistudio.com/wiki/default'
+
   'If ExitWith statement':
       'prefix': 'if_exitWith'
       'body': """
@@ -82,6 +89,7 @@
     """
     'description': 'Array incrementing loop'
     'descriptionMoreURL': 'https://community.bistudio.com/wiki/forEach'
+
   'For Loop (ARRAY)':
     'prefix': 'for_array'
     'body': """
@@ -91,6 +99,7 @@
     """
     'description': 'C-like for loop'
     'descriptionMoreURL': 'https://community.bistudio.com/wiki/for_forspec'
+
   'For Loop (VAR)':
     'prefix': 'for_var'
     'body': """
@@ -100,6 +109,7 @@
     """
     'description': 'Loop from value to value'
     'descriptionMoreURL': 'https://community.bistudio.com/wiki/for_var'
+
   'For Loop Step (VAR)':
     'prefix': 'for_var_step'
     'body': """
@@ -109,6 +119,7 @@
     """
     'description': 'Loop from value to value with custom step'
     'descriptionMoreURL': 'https://community.bistudio.com/wiki/for_var'
+
   'While Loop':
     'prefix': 'while'
     'body': """
@@ -152,130 +163,8 @@
     'description': 'Function Header per ACE3 guidelines.'
     'descriptionMoreURL': 'http://ace3mod.com/wiki/development/coding-guidelines.html#3-1-function-definitions'

-  # CBA/ACE Macros
-  'GVAR':
-    'prefix': 'GVAR'
-    'body': """
-      GVAR(${1:[variable]})
-    """
-    'description': 'Expand to PREFIX_MODULE_variable'
-    'descriptionMoreURL': 'http://ace3mod.com/wiki/development/coding-guidelines.html#4-2-general-purpose-macros'
-
-  'QGVAR':
-    'prefix': 'QGVAR'
-    'body': """
-      QGVAR(${1:[variable]})
-    """
-    'description': ''
-    'descriptionMoreURL': 'http://ace3mod.com/wiki/development/coding-guidelines.html#4-2-general-purpose-macros'
-
-  'EGVAR':
-    'prefix': 'EGVAR'
-    'body': """
-      EGVAR(${1:[component]}),${2:[variable]})
-    """
-    'description': ''
-    'descriptionMoreURL': 'http://ace3mod.com/wiki/development/coding-guidelines.html#4-2-general-purpose-macros'
-
-  'QEGVAR':
-    'prefix': 'QEGVAR'
-    'body': """
-      QEGVAR(${1:[component]}),${2:[variable]})
-    """
-    'description': ''
-    'descriptionMoreURL': 'http://ace3mod.com/wiki/development/coding-guidelines.html#4-2-general-purpose-macros'
-
-  'FUNC':
-    'prefix': 'FUNC'
-    'body': """
-      FUNC(${1:[function name]})
-    """
-    'description': ''
-    'descriptionMoreURL': 'http://ace3mod.com/wiki/development/coding-guidelines.html#4-2-general-purpose-macros'
-
-  'EFUNC':
-    'prefix': 'EFUNC'
-    'body': """
-      EFUNC(${1:[component name]}),${2:[function name]})
-    """
-    'description': ''
-    'descriptionMoreURL': 'http://ace3mod.com/wiki/development/coding-guidelines.html#4-2-general-purpose-macros'
-
-  'DFUNC':
-    'prefix': 'DFUNC'
-    'body': """
-      DFUNC(${1:[function name]})
-    """
-    'description': ''
-    'descriptionMoreURL': 'http://ace3mod.com/wiki/development/coding-guidelines.html#4-2-general-purpose-macros'
-
-  'DEFUNC':
-    'prefix': 'DEFUNC'
-    'body': """
-      DEFUNC(${1:[component name]}),${2:[function name]})
-    """
-    'description': ''
-    'descriptionMoreURL': 'http://ace3mod.com/wiki/development/coding-guidelines.html#4-2-general-purpose-macros'
-
-  'QFUNC':
-    'prefix': 'QFUNC'
-    'body': """
-      QFUNC(${1:[function name]})
-    """
-    'description': ''
-    'descriptionMoreURL': 'http://ace3mod.com/wiki/development/coding-guidelines.html#4-2-general-purpose-macros'
-
-  'QEFUNC':
-    'prefix': 'QEFUNC'
-    'body': """
-      QEFUNC(${1:[component name]}),${2:[function name]})
-    """
-    'description': ''
-    'descriptionMoreURL': 'http://ace3mod.com/wiki/development/coding-guidelines.html#4-2-general-purpose-macros'
-
-  'QUOTE':
-    'prefix': 'QUOTE'
-    'body': """
-      QUOTE(${1:[Content]})
-    """
-    'description': ''
-    'descriptionMoreURL': 'http://ace3mod.com/wiki/development/coding-guidelines.html#4-2-general-purpose-macros'
-
-  'LSTRING':
-    'prefix': 'LSTRING'
-    'body': """
-      LSTRING(${1:[String table entry]})
-    """
-    'description': ''
-    'descriptionMoreURL': 'http://ace3mod.com/wiki/development/coding-guidelines.html#4-2-general-purpose-macros'
-
-  'ELSTRING':
-    'prefix': 'ELSTRING'
-    'body': """
-      ELSTRING(${1:[Component]}),${2:[String table entry]})
-    """
-    'description': ''
-    'descriptionMoreURL': 'http://ace3mod.com/wiki/development/coding-guidelines.html#4-2-general-purpose-macros'
-
-  'CSTRING':
-    'prefix': 'CSTRING'
-    'body': """
-      CSTRING(${1:[String table entry]})
-    """
-    'description': ''
-    'descriptionMoreURL': 'http://ace3mod.com/wiki/development/coding-guidelines.html#4-2-general-purpose-macros'
-
-  'ECSTRING':
-    'prefix': 'ECSTRING'
-    'body': """
-      ELSTRING(${1:[Component]}),${2:[String table entry]})
-    """
-    'description': ''
-    'descriptionMoreURL': 'http://ace3mod.com/wiki/development/coding-guidelines.html#4-2-general-purpose-macros'
-
-
-
-# Config snippets
+
+# Config
 '.source.cpp, .source.hpp':
   # ACE3
   'ACE3 Settings Entry':
@@ -292,6 +181,9 @@
     'description': 'ACE_Settings Entry (without SCALAR values)'
     'descriptionMoreURL': 'http://ace3mod.com/wiki/framework/settings.html'

+
+# Code & Config
+'.source.sqf, .source.cpp, .source.hpp':
   # CBA/ACE Macros
   'GVAR':
     'prefix': 'GVAR'


No more log file

No more log file

--- src/deserialize-svg.coffee
+++ src/deserialize-svg.coffee
@@ -34,7 +34,6 @@

   parentNode = null
   window.objs = objects
-  # console.log window.objs
   objects

 # Convert nodes to svg.js elements


Updated TwolineTitle for android

Updated TwolineTitle for android

--- Framework/Views/Controls/TwoLineTitle_Framework_Android.coffee
+++ Framework/Views/Controls/TwoLineTitle_Framework_Android.coffee
@@ -4,28 +4,20 @@
     super options

   createTitle: =>
-    title = super
-    title.updateLayout {
-      height: Ti.UI.SIZE
-      font: { fontSize: 22 }
-    }
-
+    title = super()
+    title.setHeight(Ti.UI.SIZE)
+    title.setFont({ fontSize: 22 })
     title

   createSubTitle: =>
-    subTitle = super
-    subTitle.updateLayout {
-      height: Ti.UI.SIZE
-      font: { fontSize: 18 }
-    }
-
+    subTitle = super()
+    subTitle.setHeight(height: Ti.UI.SIZE)
+    subTitle.setFont({ fontSize: 18 })
     subTitle

   createBigTitle: =>
-    bigTitle = super
-    bigTitle.updateLayout {
-      height: Ti.UI.SIZE
-      font: { fontSize: 28, fontWeight: 'bold' }
-    }
+    bigTitle = super()
+    bigTitle.setHeight(Ti.UI.SIZE)
+    bigTitle.setFont({ fontSize: 28, fontWeight: 'bold' })

     bigTitle


Clean up update logic and dataflow

Clean up update logic and dataflow

--- source/coffee/index.coffee
+++ source/coffee/index.coffee
@@ -86,58 +86,64 @@
     @wsPlans = ko.observableArray()
     @wsKeys = {}

-    @updateTransaction = (data) =>
-      if data?.transaction?
-        @sKey = data.transaction.session_key
-        @txID = data.transaction.txid
-
-    @poll = (url, cb, timeout=@config?.timeout?.long) =>
-      rePoll = (throttle=false, update=false) =>
-        doit = (=> @poll "/roush/nodes/updates/#{@sKey}/#{@txID}?poll", cb, timeout)
-        if update?
-          @getData "/roush/updates", (data) =>
-            @updateTransaction data
-            setTimeout doit, if throttle then 1000 else 1
+    @poll = (url, cb, timeout=@config?.timeout?.long ? 30000) =>
+      rePoll = (throttle=false) =>
+        setTimeout (=> @poll "/roush/nodes/updates/#{@sKey}/#{@txID}?poll", cb, timeout), if throttle then 1000 else 1
+
+      updateTransaction = (trans, cb) =>
+        unless trans?
+          @getData "/roush/updates", (pass) =>
+            updateTransaction pass?.transaction
+            cb() if cb?
         else
-          setTimeout doit, if throttle then 1000 else 1
-
-      $.ajax
-        url: url
-        success: (data) =>
-          cb data, (-> rePoll data)
-        error: (jqXHR, textStatus, errorThrown) =>
-          switch jqXHR.status
-            when 410 # Gone, cycle txID
-              rePoll false, true
-            else # Other errors
-              console.log "Error (#{jqXHR.status}): #{errorThrown}"
-              rePoll true
-        dataType: "json"
-        timeout: timeout ? 30000
+          @sKey = trans.session_key
+          @txID = trans.txid
+
+      unless @sKey? and @txID?
+        updateTransaction null, -> rePoll true
+      else
+        $.ajax
+          url: url
+          success: (data) ->
+            cb data.nodes
+            updateTransaction data.transaction
+            rePoll()
+          error: (jqXHR, textStatus, errorThrown) ->
+            switch jqXHR.status
+              when 410 # Gone, cycle transaction
+                updateTransaction null, -> rePoll()
+              when 502 # Bad gateway; proxy failure
+                rePoll true
+              else # Other errors
+                if textStatus is "timeout"
+                  rePoll()
+                else
+                  console.log "Error (#{jqXHR.status}): #{textStatus} - #{errorThrown}"
+                  rePoll true
+          dataType: "json"
+          timeout: timeout

     # Get config and grab initial set of nodes
     @getData "/api/config", (data) =>
       # Store config
       @config = data

-      @getData "/roush/updates", (data) =>
-        @updateTransaction data
-        # Start long-poller
-        @poll "/roush/nodes/updates/#{@sKey}/#{@txID}?poll", (data, cb) =>
-          pnodes = []
-          resolver = (stack) =>
-            id = stack.pop()
-            unless id? # End of ID list
-              setTimeout @updateNodes(nodes: pnodes, @wsTemp, @wsKeys), 1000
-              cb() if cb?
-            else
-              @getData "/roush/nodes/#{id}", (node) =>
-                pnodes.push node.node
-                resolver stack
-          resolver data.nodes
-
-        # Load initial data, and poll every config.interval ms
-        @getNodes "/roush/nodes/", @wsTemp, @wsKeys
+      # Start long-poller
+      @poll "/roush/nodes/updates/#{@sKey}/#{@txID}?poll", (nodes, cb) =>
+        pnodes = []
+        resolver = (stack) =>
+          id = stack.pop()
+          unless id? # End of ID list
+            @updateNodes nodes: pnodes, @wsTemp, @wsKeys
+            cb() if cb?
+          else
+            @getData "/roush/nodes/#{id}", (node) =>
+              pnodes.push node.node
+              resolver stack
+        resolver nodes
+
+      # Load initial data
+      @getNodes "/roush/nodes/", @wsTemp, @wsKeys

     @siteActive = ntrapy.selector (data) =>
       null # TODO:


hypothesis/dom-text-mapper#12 fix infinite loop on strange whitespace

--- src/dom_text_mapper.coffee
+++ src/dom_text_mapper.coffee
@@ -527,11 +527,11 @@

     # the HTML source of the text inside a text element.
 #    @_log "Calculating source position at " + match.element.path
-    sourceText = match.element.node.data.replace /\n/g, " "
-#    @_log "sourceText is '" + sourceText + "'"
+    sourceText = match.element.node.data.replace /[\s\xA0]/g, " "
+#    @log "sourceText is '" + sourceText + "'"

     # what gets displayed, when the node is processed by the browser.
-    displayText = match.element.content
+    displayText = match.element.content.replace /[\s\xA0]/g, " "
 #    @_log "displayText is '" + displayText + "'"

     if displayText.length > sourceText.length


#184: only emit slidestart on slide start, as opposed to on change

--- modules/slider/main/index.coffee
+++ modules/slider/main/index.coffee
@@ -16,8 +16,6 @@
 # is being dragged.
 slide = (e) ->
   _ = @_
-
-  @emit 'slidestart', @value()
   _.mouseDown = true

   _.pointerMoveHandler = (e) => slide.call this, e
@@ -164,7 +162,9 @@
       .classed('hx-slider-double', @options.type is 'range')
       .classed('hx-slider-discrete', _.isDiscrete)
       .on 'pointerdown', 'hx.slider', (e) =>
-        if not _.disabled then slide.call this, e
+        if not _.disabled
+          @emit 'slidestart', @value()
+          slide.call this, e

     _.range = _.container.append('div').class('hx-slider-range')


Removed data labels from world map

Removed data labels from world map

--- app/assets/javascripts/cleantheme/maps.js.coffee
+++ app/assets/javascripts/cleantheme/maps.js.coffee
@@ -12,6 +12,12 @@
       text: null
     legend:
       enabled: false
+      # layout: 'horizontal'
+      # borderWidth: 0
+      # backgroundColor: 'rgba(255,255,255,0.85)'
+      # floating: true
+      # verticalAlign: 'top'
+      # y: 25
     credits:
       enabled: false
     mapNavigation:
@@ -27,7 +33,7 @@
         hover:
           color: '#BADA55'
       dataLabels:
-        enabled: true
+        enabled: false # true
         format: '{point.name}'
       tooltip:
         headerFormat: ''


Remove js logging

Remove js logging

--- app/assets/javascripts/doorkeeper_sync.js.coffee
+++ app/assets/javascripts/doorkeeper_sync.js.coffee
@@ -45,9 +45,6 @@
             when 404
               $statusMessage.text('イベントが見つかりません。URLを確認してください。')
             else
-              console.log("XMLHttpRequest: #{XMLHttpRequest.status}")
-              console.log("textStatus: #{textStatus}")
-              console.log("errorThrown: #{errorThrown}")
               $statusMessage.text('エラーが発生しました。しばらく経ってから再度実行してください。')
           $statusMessage.addClass('result-error')
           $('.result-icon-error').show()


Fixed bug on full sync

Fixed bug on full sync

--- app/assets/javascripts/views/dreams/index.coffee
+++ app/assets/javascripts/views/dreams/index.coffee
@@ -11,8 +11,12 @@
     @collection.on('destroy', @focusOnNew)

   render: =>
+    @addAll()
+    @
+
+  addAll: ->
+    @$('#dreams').html ''
     @collection.each @addOne
-    @

   addOne: (dream) =>
     view = new App.Views.DreamsItem(model: dream)


Invalidate links when switching a node between collector/non-collector [#145768155]