applied aligner just for exercose

applied aligner just for exercose

--- spec/text-object-spec.coffee
+++ spec/text-object-spec.coffee
@@ -364,9 +364,9 @@
         close = [0, 3]
         beforeEach ->
           set {text}
-        it "case-1 normal", -> check open, 'd', text: textFinal, cursor: [0, 2]
+        it "case-1 normal", -> check open,  'd', text: textFinal, cursor: [0, 2]
         it "case-2 normal", -> check close, 'd', text: textFinal, cursor: [0, 2]
-        it "case-3 visual", -> check open, 'v', {selectedText}
+        it "case-3 visual", -> check open,  'v', {selectedText}
         it "case-4 visual", -> check close, 'v', {selectedText}
     describe "a-double-quote", ->
       originalText = '" something in here and in "here" "'
@@ -394,9 +394,9 @@
         close = [0, 3]
         beforeEach ->
           set {text}
-        it "case-1 normal", -> check open, 'd', text: textFinal, cursor: [0, 1]
+        it "case-1 normal", -> check open,  'd', text: textFinal, cursor: [0, 1]
         it "case-2 normal", -> check close, 'd', text: textFinal, cursor: [0, 1]
-        it "case-3 visual", -> check open, 'v', {selectedText}
+        it "case-3 visual", -> check open,  'v', {selectedText}
         it "case-4 visual", -> check close, 'v', {selectedText}
   describe "SingleQuote", ->
     describe "inner-single-quote", ->
@@ -469,9 +469,9 @@
         close = [0, 3]
         beforeEach ->
           set {text}
-        it "case-1 normal", -> check open, 'd', text: textFinal, cursor: [0, 2]
+        it "case-1 normal", -> check open,  'd', text: textFinal, cursor: [0, 2]
         it "case-2 normal", -> check close, 'd', text: textFinal, cursor: [0, 2]
-        it "case-3 visual", -> check open, 'v', {selectedText}
+        it "case-3 visual", -> check open,  'v', {selectedText}
         it "case-4 visual", -> check close, 'v', {selectedText}
     describe "a-single-quote", ->
       originalText = "' something in here and in 'here' '"
@@ -611,9 +611,9 @@
         close = [0, 3]
         beforeEach ->
           set {text}
-        it "case-1 normal", -> check open, 'd', text: textFinal, cursor: [0, 2]
+        it "case-1 normal", -> check open,  'd', text: textFinal, cursor: [0, 2]
         it "case-2 normal", -> check close, 'd', text: textFinal, cursor: [0, 2]
-        it "case-3 visual", -> check open, 'v', {selectedText}
+        it "case-3 visual", -> check open,  'v', {selectedText}
         it "case-4 visual", -> check close, 'v', {selectedText}

       describe "change mode to characterwise", ->
@@ -704,9 +704,9 @@
         close = [0, 3]
         beforeEach ->
           set {text}
-        it "case-1 normal", -> check open, 'd', text: textFinal, cursor: [0, 1]
+        it "case-1 normal", -> check open,  'd', text: textFinal, cursor: [0, 1]
         it "case-2 normal", -> check close, 'd', text: textFinal, cursor: [0, 1]
-        it "case-3 visual", -> check open, 'v', {selectedText}
+        it "case-3 visual", -> check open,  'v', {selectedText}
         it "case-4 visual", -> check close, 'v', {selectedText}

       describe "change mode to characterwise", ->
@@ -799,9 +799,9 @@
         close = [0, 3]
         beforeEach ->
           set {text}
-        it "case-1 normal", -> check open, 'd', text: textFinal, cursor: [0, 2]
+        it "case-1 normal", -> check open,  'd', text: textFinal, cursor: [0, 2]
         it "case-2 normal", -> check close, 'd', text: textFinal, cursor: [0, 2]
-        it "case-3 visual", -> check open, 'v', {selectedText}
+        it "case-3 visual", -> check open,  'v', {selectedText}
         it "case-4 visual", -> check close, 'v', {selectedText}
     describe "a-angle-bracket", ->
       beforeEach ->
@@ -830,24 +830,24 @@
         close = [0, 3]
         beforeEach ->
           set {text}
-        it "case-1 normal", -> check open, 'd', text: textFinal, cursor: [0, 1]
+        it "case-1 normal", -> check open,  'd', text: textFinal, cursor: [0, 1]
         it "case-2 normal", -> check close, 'd', text: textFinal, cursor: [0, 1]
-        it "case-3 visual", -> check open, 'v', {selectedText}
+        it "case-3 visual", -> check open,  'v', {selectedText}
         it "case-4 visual", -> check close, 'v', {selectedText}

   describe "AllowForwarding family", ->
     beforeEach ->
       atom.keymaps.add "test",
         'atom-text-editor.vim-mode-plus.operator-pending-mode, atom-text-editor.vim-mode-plus.visual-mode':
-          'i }':  'vim-mode-plus:inner-curly-bracket-allow-forwarding'
-          'i >':  'vim-mode-plus:inner-angle-bracket-allow-forwarding'
-          'i ]':  'vim-mode-plus:inner-square-bracket-allow-forwarding'
-          'i )':  'vim-mode-plus:inner-parenthesis-allow-forwarding'
-
-          'a }':  'vim-mode-plus:a-curly-bracket-allow-forwarding'
-          'a >':  'vim-mode-plus:a-angle-bracket-allow-forwarding'
-          'a ]':  'vim-mode-plus:a-square-bracket-allow-forwarding'
-          'a )':  'vim-mode-plus:a-parenthesis-allow-forwarding'
+          'i }': 'vim-mode-plus:inner-curly-bracket-allow-forwarding'
+          'i >': 'vim-mode-plus:inner-angle-bracket-allow-forwarding'
+          'i ]': 'vim-mode-plus:inner-square-bracket-allow-forwarding'
+          'i )': 'vim-mode-plus:inner-parenthesis-allow-forwarding'
+
+          'a }': 'vim-mode-plus:a-curly-bracket-allow-forwarding'
+          'a >': 'vim-mode-plus:a-angle-bracket-allow-forwarding'
+          'a ]': 'vim-mode-plus:a-square-bracket-allow-forwarding'
+          'a )': 'vim-mode-plus:a-parenthesis-allow-forwarding'

       set
         text: """
@@ -892,31 +892,19 @@
           111}
           """
       describe "forwarding inner", ->
-        it "select forwarding range", ->
-          set cursor: [1, 0]; ensure "v i }", selectedText: textOneInner
-        it "select forwarding range", ->
-          set cursor: [2, 0]; ensure "v i }", selectedText: "22"
-        it "[case-1] no forwarding open pair, fail to find", ->
-          set cursor: [0, 0]; ensure "v i }", selectedText: '0', cursor: [0, 1]
-        it "[case-2] no forwarding open pair, select enclosed", ->
-          set cursor: [1, 4]; ensure "v i }", selectedText: textOneInner
-        it "[case-3] no forwarding open pair, select enclosed", ->
-          set cursor: [3, 0]; ensure "v i }", selectedText: textOneInner
-        it "[case-3] no forwarding open pair, select enclosed", ->
-          set cursor: [4, 0]; ensure "v i }", selectedText: textOneInner
+        it "select forwarding range", ->           set cursor: [1, 0]; ensure "v i }", selectedText: textOneInner
+        it "select forwarding range", ->           set cursor: [2, 0]; ensure "v i }", selectedText: "22"
+        it "[c1] no fwd open, fail to find", ->    set cursor: [0, 0]; ensure "v i }", selectedText: '0', cursor: [0, 1]
+        it "[c2] no fwd open, select enclosed", -> set cursor: [1, 4]; ensure "v i }", selectedText: textOneInner
+        it "[c3] no fwd open, select enclosed", -> set cursor: [3, 0]; ensure "v i }", selectedText: textOneInner
+        it "[c3] no fwd open, select enclosed", -> set cursor: [4, 0]; ensure "v i }", selectedText: textOneInner
       describe "forwarding a", ->
-        it "select forwarding range", ->
-          set cursor: [1, 0]; ensure "v a }", selectedText: textOneA
-        it "select forwarding range", ->
-          set cursor: [2, 0]; ensure "v a }", selectedText: "{22}"
-        it "[case-1] no forwarding open pair, fail to find", ->
-          set cursor: [0, 0]; ensure "v a }", selectedText: '0', cursor: [0, 1]
-        it "[case-2] no forwarding open pair, select enclosed", ->
-          set cursor: [1, 4]; ensure "v a }", selectedText: textOneA
-        it "[case-3] no forwarding open pair, select enclosed", ->
-          set cursor: [3, 0]; ensure "v a }", selectedText: textOneA
-        it "[case-3] no forwarding open pair, select enclosed", ->
-          set cursor: [4, 0]; ensure "v a }", selectedText: textOneA
+        it "select forwarding range", ->           set cursor: [1, 0]; ensure "v a }", selectedText: textOneA
+        it "select forwarding range", ->           set cursor: [2, 0]; ensure "v a }", selectedText: "{22}"
+        it "[c1] no fwd open, fail to find", ->    set cursor: [0, 0]; ensure "v a }", selectedText: '0', cursor: [0, 1]
+        it "[c2] no fwd open, select enclosed", -> set cursor: [1, 4]; ensure "v a }", selectedText: textOneA
+        it "[c3] no fwd open, select enclosed", -> set cursor: [3, 0]; ensure "v a }", selectedText: textOneA
+        it "[c3] no fwd open, select enclosed", -> set cursor: [4, 0]; ensure "v a }", selectedText: textOneA

   describe "AnyPairAllowForwarding", ->
     beforeEach ->
@@ -981,22 +969,22 @@
           set {text}

         # Select
-        it "[1] forwarding", -> check [1, 0], 'v', {selectedText}
-        it "[2] openTag leftmost", -> check [1, 2], 'v', {selectedText}
-        it "[3] openTag rightmost", -> check [1, 8], 'v', {selectedText}
-        it "[4] Inner text", -> check [1, 10], 'v', {selectedText}
-        it "[5] closeTag leftmost", -> check [1, 14], 'v', {selectedText}
-        it "[6] closeTag rightmost", -> check [1, 21], 'v', {selectedText}
-        it "[7] right of closeTag", -> check [2, 0], 'v', {selectedText: innerABC}
+        it "[1] forwarding",         -> check [1,  0],  'v', {selectedText}
+        it "[2] openTag leftmost",   -> check [1,  2],  'v', {selectedText}
+        it "[3] openTag rightmost",  -> check [1,  8],  'v', {selectedText}
+        it "[4] Inner text",         -> check [1,  10], 'v', {selectedText}
+        it "[5] closeTag leftmost",  -> check [1,  14], 'v', {selectedText}
+        it "[6] closeTag rightmost", -> check [1,  21], 'v', {selectedText}
+        it "[7] right of closeTag",  -> check [2,  0],  'v', {selectedText: innerABC}

         # Delete
-        it "[8] forwarding", -> check [1, 0], 'd', {text: textAfterDeleted}
-        it "[9] openTag leftmost", -> check [1, 2], 'd', {text: textAfterDeleted}
-        it "[10] openTag rightmost", -> check [1, 8], 'd', {text: textAfterDeleted}
-        it "[11] Inner text", -> check [1, 10], 'd', {text: textAfterDeleted}
-        it "[12] closeTag leftmost", -> check [1, 14], 'd', {text: textAfterDeleted}
+        it "[8] forwarding",          -> check [1, 0],  'd', {text: textAfterDeleted}
+        it "[9] openTag leftmost",    -> check [1, 2],  'd', {text: textAfterDeleted}
+        it "[10] openTag rightmost",  -> check [1, 8],  'd', {text: textAfterDeleted}
+        it "[11] Inner text",         -> check [1, 10], 'd', {text: textAfterDeleted}
+        it "[12] closeTag leftmost",  -> check [1, 14], 'd', {text: textAfterDeleted}
         it "[13] closeTag rightmost", -> check [1, 21], 'd', {text: textAfterDeleted}
-        it "[14] right of closeTag", -> check [2, 0], 'd', {text: "<abc></abc>"}
+        it "[14] right of closeTag",  -> check [2, 0],  'd', {text: "<abc></abc>"}

       describe "expansion and deletion", ->
         beforeEach ->
@@ -1154,22 +1142,22 @@
           set {text}

         # Select
-        it "[1] forwarding", -> check [1, 0], 'v', {selectedText}
-        it "[2] openTag leftmost", -> check [1, 2], 'v', {selectedText}
-        it "[3] openTag rightmost", -> check [1, 8], 'v', {selectedText}
-        it "[4] Inner text", -> check [1, 10], 'v', {selectedText}
-        it "[5] closeTag leftmost", -> check [1, 14], 'v', {selectedText}
+        it "[1] forwarding",         -> check [1, 0],  'v', {selectedText}
+        it "[2] openTag leftmost",   -> check [1, 2],  'v', {selectedText}
+        it "[3] openTag rightmost",  -> check [1, 8],  'v', {selectedText}
+        it "[4] Inner text",         -> check [1, 10], 'v', {selectedText}
+        it "[5] closeTag leftmost",  -> check [1, 14], 'v', {selectedText}
         it "[6] closeTag rightmost", -> check [1, 21], 'v', {selectedText}
-        it "[7] right of closeTag", -> check [2, 0], 'v', {selectedText: aABC}
+        it "[7] right of closeTag",  -> check [2, 0],  'v', {selectedText: aABC}

         # Delete
-        it "[8] forwarding", -> check [1, 0], 'd', {text: textAfterDeleted}
-        it "[9] openTag leftmost", -> check [1, 2], 'd', {text: textAfterDeleted}
-        it "[10] openTag rightmost", -> check [1, 8], 'd', {text: textAfterDeleted}
-        it "[11] Inner text", -> check [1, 10], 'd', {text: textAfterDeleted}
-        it "[12] closeTag leftmost", -> check [1, 14], 'd', {text: textAfterDeleted}
+        it "[8] forwarding",          -> check [1, 0],  'd', {text: textAfterDeleted}
+        it "[9] openTag leftmost",    -> check [1, 2],  'd', {text: textAfterDeleted}
+        it "[10] openTag rightmost",  -> check [1, 8],  'd', {text: textAfterDeleted}
+        it "[11] Inner text",         -> check [1, 10], 'd', {text: textAfterDeleted}
+        it "[12] closeTag leftmost",  -> check [1, 14], 'd', {text: textAfterDeleted}
         it "[13] closeTag rightmost", -> check [1, 21], 'd', {text: textAfterDeleted}
-        it "[14] right of closeTag", -> check [2, 0], 'd', {text: ""}
+        it "[14] right of closeTag",  -> check [2, 0],  'd', {text: ""}

   describe "SquareBracket", ->
     describe "inner-square-bracket", ->


add missing rect method to tiled map class

--- src/drawable/TiledMap.coffee
+++ src/drawable/TiledMap.coffee
@@ -136,3 +136,15 @@
     ###
     addTileset: (tilesetName, assetName) ->
         @tilesets_images[tilesetName] = assetName
+
+
+    ###*
+     # Map rect
+     # @method rect
+     # @return {Object}
+    ###
+    rect: ->
+        x: @x
+        y: @y
+        width: @map.width * @tile_width
+        height: @map.height * @tile_height


better async handling.  remove xhr from start function

--- src/ubret/spacewarp_viewer/initialize.coffee
+++ src/ubret/spacewarp_viewer/initialize.coffee
@@ -53,18 +53,24 @@

   constructor: (selector) ->
     super selector
-    # Default stretch
+
+    # Set parameters
     @stretch = 'linear'
-
-    # Run when the WebFITS API is received
-    @on 'swviewer:ready', =>
-      el = document.querySelector(@selector)
-      @wfits = new astro.WebFITS(el, @dimension)
-      unless @wfits.ctx?
-        alert 'Something went wrong initializing the context'
-
-      @unbind 'swviewer:ready'
-
+    @collection = new Layers()
+
+    # Set various deferred objects to handle asynchronous requests.
+    @dfs =
+      webfits: new $.Deferred()
+      u: new $.Deferred()
+      g: new $.Deferred()
+      r: new $.Deferred()
+      i: new $.Deferred()
+      z: new $.Deferred()
+
+    @getApi()
+    @on 'data-received', @requestChannels
+
+  # Request the appropriate WebFITS API (WebGL or Canvas)
   getApi: =>
     unless DataView?
       alert 'Sorry, your browser does not support features needed for this tool.'
@@ -78,40 +84,21 @@
     lib = if context? then 'gl' else 'canvas'
     url = "javascripts/webfits-#{lib}.js"
     $.getScript(url, =>
-      @trigger 'swviewer:ready'
+      @initWebFITS()
+      @dfs.webfits.resolve()
     )

-  start: =>
-    # Request the appropriate WebFITS API (canvas or webgl)
-    @getApi()
-
-    # Initialize a collections for storing FITS images
-    @collection = new Layers()
+  # Request FITS files for each channel
+  requestChannels: =>
+    console.log 'requestChannels'

     subject = @opts.data[0]
     prefix  = subject.metadata.id

-    # Create one deferred for each band
-    dfs = []
-    for band, index in @bands
-      dfs.push new $.Deferred()
-
-    # Setup callback for when all requests are received
-    $.when.apply(@, dfs)
-      .done( (e) =>
-        @computeNormalizedScales()
-        scales = @collection.getColorScales()
-
-        @wfits.setAlpha(@defaultAlpha)
-        @wfits.setQ(@defaultQ)
-        @wfits.setScales.apply(@wfits, scales)
-        @wfits.setupControls()
-
-        # Set color composite as default
-        @trigger 'swviewer:loaded'
-      )
-
-    # Request FITS images
+    # Set callback for when all channels and WebFITS Api received
+    $.when.apply(null, _.values(@dfs))
+      .done(@allChannelsReceived)
+
     for band, index in @bands
       do (band, index) =>
         path = "#{@source}#{prefix}_#{band}.fits.fz"
@@ -135,9 +122,34 @@

             # Load texture
             @wfits.loadImage(band, arr, dataunit.width, dataunit.height)
-            dfs[index].resolve()
+            @dfs[band].resolve()
           )
         )
+
+  # Initialize a WebFITS object
+  initWebFITS: =>
+    el = document.querySelector(@selector)
+    @wfits = new astro.WebFITS(el, @dimension)
+
+    unless @wfits.ctx?
+      alert 'Something went wrong initializing the context'
+
+  # Call when all FITS received and WebFITS library is received
+  allChannelsReceived: (e) =>
+    console.log 'allChannelsReceived'
+    @dfs = undefined
+
+    @computeNormalizedScales()
+    scales = @collection.getColorScales()
+
+    @wfits.setAlpha(@defaultAlpha)
+    @wfits.setQ(@defaultQ)
+    @wfits.setScales.apply(@wfits, scales)
+    @wfits.setupControls()
+    @trigger 'swviewer:loaded'
+
+  start: =>
+    console.log 'start'

   log10: (x) ->
     return Math.log(x) / Math.log(10)


First didSave device call happens immediately instead of waiting 2s then waits 2s

--- src/flow-deploy-model.coffee
+++ src/flow-deploy-model.coffee
@@ -16,12 +16,13 @@
   didSave: (id, callback=->) =>
     meshbluHttp = new @MeshbluHttp @userMeshbluConfig
     timeLimit = _.now() + @TIMEOUT
+    wait = 0
     @async.doUntil (next) =>
       return next new Error 'Save Timeout' if _.now() > timeLimit
       setTimeout =>
         meshbluHttp.device uuid: @flowId, next
-      , @WAIT
-
+      , wait
+      wait = @WAIT
     , (device) =>
       return device.stateId == id
     , (error) =>


Fix HALP

Fix HALP

--- modules/help.coffee
+++ modules/help.coffee
@@ -38,6 +38,6 @@
     #   msg.reply 'Check your DMs!' if msg.channel.guild_id

   filtersCommandFunction: (msg,args)=>
-    msg.reply 'To learn more about audio filters, check this link: https://focabot.thebit.link/filters?prefix=#{encodeURIComponent pfx}'
+    msg.reply "To learn more about audio filters, check this link: https://focabot.thebit.link/filters?prefix=#{encodeURIComponent pfx}"

 module.exports = HelpModule


Tweak how links are truncated.

Tweak how links are truncated.

--- src/linkview/linkview.coffee
+++ src/linkview/linkview.coffee
@@ -96,12 +96,16 @@
             head = parts.splice(0, 1)
             tail = []

+            # strip file extension
+            lastPart = parts.pop()
+            lastPart = lastPart?.replace ///(index)?\.[a-z]+$///i, ''
+            if lastPart
+                parts.push(lastPart)
+
             # Append very last URL fragment, truncating if required
             lengthLeft = @maxLength - constructUrl(head, tail).length
             if lengthLeft > 0 and parts.length
                 fragment = parts.pop()
-                # strip file extension
-                fragment = fragment.replace ///(index)?\.[a-z]+$///i, ''
                 tail.push(truncate(fragment, lengthLeft))

             # Insert very first URL fragment, truncating if required
@@ -110,7 +114,7 @@
                 fragment = parts.shift()
                 head.push(truncate(fragment, lengthLeft))

-            if tail.length and parts.length
+            if parts.length
                 head.push('\u22EF')  # Midline horizontal ellipsis ⋯

             constructUrl(head, tail)


HIRE-48 removed console.log

HIRE-48 removed console.log

--- src/main/java/app/app.coffee
+++ src/main/java/app/app.coffee
@@ -10,11 +10,9 @@
     requireBase: false
             RestangularProvider.setBaseUrl('/api/')
          ).controller('NavigationCtrl', ($scope, $location, Restangular) ->
-  console.log "TEST"
   gitProperties = Restangular.one('gitProperties')
   gitProperties.get().then (data) ->
     $scope.gitPropertyDTO = data.gitPropertyDTO
-    console.log data.gitPropertyDTO
   $scope.isActive = (route) ->
     route is $location.path()
   $scope.triggerBuildInformation = ->


up fabricate

up fabricate

--- node/fabricate.coffee
+++ node/fabricate.coffee
@@ -545,5 +545,15 @@
       hr_video_url: "http://static.artsy.net/media/max_two_x_two_900"
       image_versions: ["large_rectangle","medium_rectangle","small_square","medium_square","large_square","large_cinematic"]
       image_url: '/local/videos/id/:version.jpg'
+
+    when 'bidder_position'
+      active: true
+      bid_max: false
+      created_at: "2013-11-14T00:03:27Z"
+      highest_bid: null
+      id: "5284134f8b3b81a906000003"
+      max_bid_amount_cents: 310000
+      suggested_next_bid_cents: 325000
+      updated_at: "2013-11-14T00:03:27Z"

   , extObj


when monitoring log, prevent error on window close

--- init-nw.coffee
+++ init-nw.coffee
@@ -138,7 +138,7 @@
     htmlEsc = (s) -> s.replace /./g, (x) -> htmlChars[x] || x
     # $(window).on 'error', (e) ->
     process.on 'uncaughtException', (e) ->
-      window.lastError = e
+      if window then window.lastError = e
       info = """
         IDE: #{JSON.stringify D.versionInfo}
         Interpreter: #{JSON.stringify(D.remoteIdentification || null)}


renamed variable D.editorsOnTop -> D.floatOnTop

--- init-nw.coffee
+++ init-nw.coffee
@@ -50,9 +50,9 @@
         width:  +urlParams.width
         height: +urlParams.height
     else
-      D.floatingWindows = []; D.editorsOnTop = 0
-      nww.on 'focus', -> (for x in D.floatingWindows then x.setAlwaysOnTop !!D.editorsOnTop); return
-      nww.on 'blur',  -> (for x in D.floatingWindows then x.setAlwaysOnTop false           ); return
+      D.floatingWindows = []; D.floatOnTop = 0
+      nww.on 'focus', -> (for x in D.floatingWindows then x.setAlwaysOnTop !!D.floatOnTop); return
+      nww.on 'blur',  -> (for x in D.floatingWindows then x.setAlwaysOnTop false         ); return
       if localStorage.pos then try
         pos = JSON.parse localStorage.pos
         restoreWindow nww, x: pos[0], y: pos[1], width: pos[2], height: pos[3]


schema evolution error workaround

schema evolution error workaround

--- chrome/content/zotero-better-bibtex/zotero-better-bibtex.coffee
+++ chrome/content/zotero-better-bibtex/zotero-better-bibtex.coffee
@@ -201,7 +201,7 @@

   if version < 8
     Zotero.DB.query("
-      create table betterbibtex.autoexport (
+      create table if not exists betterbibtex.autoexport (
         id integer primary key not null,
         collection_id not null,
         collection_name not null,


Finder: Setting vmRoot to appStorage is now optional.

--- client/app/MainApp/filetree/controllers/findercontroller.coffee
+++ client/app/MainApp/filetree/controllers/findercontroller.coffee
@@ -181,7 +181,7 @@
     vmRoots = (@appStorage.getValue 'vmRoots') or {}
     pipedVm = @_pipedVmName vmName
     vmRoots[pipedVm] = path
-    @appStorage.setValue 'vmRoots', vmRoots
+    @appStorage.setValue 'vmRoots', vmRoots  if @getOptions().useStorage

     @mountVm "#{vmName}:#{path}"


add jasmine test for scroll to top

add jasmine test for scroll to top

--- common/lib/xmodule/xmodule/js/spec/sequence/display_spec.coffee
+++ common/lib/xmodule/xmodule/js/spec/sequence/display_spec.coffee
@@ -134,6 +134,7 @@
     beforeEach ->
       jasmine.stubRequests()
       @sequence = new Sequence '1', 'sequence_1', @items, 'sequence', 2
+      $.scrollTo 150
       $('.sequence-nav-buttons .next a').click()

     it 'log the next sequence event', ->
@@ -142,10 +143,14 @@
     it 'call render on the next sequence', ->
       expect($('#seq_content').html()).toEqual 'Sample Problem'

+    it 'scrolls to the top of the page', ->
+      expect($('body').scrollTop()).toBe 0
+
   describe 'previous', ->
     beforeEach ->
       jasmine.stubRequests()
       @sequence = new Sequence '1', 'sequence_1', @items, 'sequence', 2
+      $.scrollTo 150
       $('.sequence-nav-buttons .prev a').click()

     it 'log the previous sequence event', ->
@@ -154,6 +159,9 @@
     it 'call render on the previous sequence', ->
       expect($('#seq_content').html()).toEqual 'Video 1'

+    it 'scrolls to the top of the page', ->
+      expect($('body').scrollTop()).toBe 0
+
   describe 'link_for', ->
     it 'return a link for specific position', ->
       sequence = new Sequence '1', 'sequence_1', @items, 2


added undo and redo to right-click menu

added undo and redo to right-click menu

--- init-nw.coffee
+++ init-nw.coffee
@@ -111,9 +111,14 @@

   D.forceCloseNWWindow = -> nww.close true; return # used to close floating windows after session is dead

-  cmenu = new gui.Menu
-  ['Cut', 'Copy', 'Paste'].forEach (x) ->
-    cmenu.append new gui.MenuItem label: x, click: (-> document.execCommand x; return); return
+  # Context menu
+  opener && D.ide = opener.D.ide
+  items = [].concat(
+    ['Cut', 'Copy', 'Paste'].map (x) -> label: x, click: -> document.execCommand x; return
+    [type: 'separator']
+    ['Undo', 'Redo'].map (x) -> label: x, click: -> D.ide?.focusedWin?.cm?[x.toLowerCase()]?(); return
+  )
+  cmenu = new gui.Menu; for item in items then cmenu.append new gui.MenuItem item
   $(document).contextmenu (e) -> cmenu.popup e.clientX, e.clientY; false

   D.readFile = fs.readFile # needed for presentation mode


fixed sendRequest

fixed sendRequest

--- src/middleware/router.coffee
+++ src/middleware/router.coffee
@@ -142,17 +142,17 @@
 	if route.type is 'tcp'
 		logger.info 'Routing tcp request'
 		return sendSocketRequest ctx, route, options
-	else if route.type is 'mllp'
+	if route.type is 'mllp'
     logger.info 'Routing mllp request'
     return sendMLLPSocketRequest ctx, route, options
-  else
+	if route.type is 'http'
 		logger.info 'Routing http(s) request'
 		return sendHttpRequest ctx, route, options

 obtainCharset = (headers) ->
         contentType = headers['content-type'] || ''
         matches =  contentType.match(/charset=([^;,\r\n]+)/i)
-        if (matches && matches[1])
+        if (matches && matches[1])
                 return matches[1]
         return  'utf-8'

@@ -252,7 +252,7 @@
 	bufs = []
 	client.on 'data', (chunk) ->
 		bufs.push chunk
-
+
 	client.on 'error', (err) -> defered.reject err

 	client.on 'end', ->


Clean up code

Clean up code

--- src/bootstrap-dialogs.coffee
+++ src/bootstrap-dialogs.coffee
@@ -51,12 +51,10 @@
     promise

   prompt: (title='Please enter a value', body) ->
-    body or= ''
-    body = """
-      #{body}
-      <input type="text">
-    """
+    $input = $('<input type="text">')
+    body = if body then [ body ] else []
+    body.push($input)
     promise = exports.dialog(title, body, [
       [ 'Cancel', -> promise.reject() ]
-      [ 'Ok', -> promise.resolve(promise.$el.find('input').val()) ]
+      [ 'Ok', -> promise.resolve($input.val()) ]
     ])


comment template folder for pullentity backbone structure

--- vendor/assets/javascripts/pullentity-backbone/app/site.js.coffee
+++ vendor/assets/javascripts/pullentity-backbone/app/site.js.coffee
@@ -1,6 +1,6 @@
 #= require_self
 #= require_tree ./helpers
-#= require_tree ../templates
+# require_tree ../templates
 #= require_tree ./models
 #= require_tree ./views
 #= require_tree ./routers


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/number_extensions.coffee
+++ src/number_extensions.coffee
@@ -111,7 +111,7 @@
   if min? and max?
     Math.min(Math.max(this, min), max)
   else if min?
-    Math.min(this, min)
+    Math.max(this, min)
   else if max?
     Math.max(this, max)
   else


Fix a bug which prevent to see tenants because of the loader

--- www/webapp/static/webapp/js/app/views/tenants/tenantsShow.coffee
+++ www/webapp/static/webapp/js/app/views/tenants/tenantsShow.coffee
@@ -1,12 +1,14 @@
 Vosae.TenantsShowView = Vosae.PageTenantView.extend
   classNames: ["outlet-tenants", "page-show-tenants"]

-  didInsertElement: ->
-    @_super()
-
-    # If user already selected or tenant or has only one tenant
-    # he will be automaticaly redirected to the tenant's dashboard
+  ###
+    If user already selected or tenant or has only one tenant
+    he will be automaticaly redirected to the tenant's dashboard,
+    otherwise we hide the loader.
+  ###
+  checkTenants: (->
     preselectedTenant = @get 'controller.session.preselectedTenant'
     tenantsLength = Vosae.Tenant.all().get('length')
     if not preselectedTenant and tenantsLength != 1
-      @get('controller.namespace').hideLoader()+      Vosae.Utilities.hideLoader()
+  ).on "didInsertElement"


Move Salamander Club to End of List

Move Salamander Club to End of List

--- src/coffee/game/leads.coffee
+++ src/coffee/game/leads.coffee
@@ -34,16 +34,6 @@
             kbs: reqs.eq 0
           active:
             rumor: reqs.gte 10
-        choice 'clubEntry',
-          'The Salamander Club'
-          '''
-          Ever since you lost your magical abilities, you've lost touch with the magical community
-          in the city.
-          The Salamander Club is a favorite watering hole of the sorcerous set and your best bet to
-          make contact with anyone who might know Mr. Brown.
-          '''
-          active:
-            cantripUp: reqs.gte 6
         choice 'pressStart',
           'The press'
           '''
@@ -63,6 +53,16 @@
             cop: reqs.eq 0
           active:
             bluebacks: reqs.gte 10
+        choice 'clubEntry',
+          'The Salamander Club'
+          '''
+          Ever since you lost your magical abilities, you've lost touch with the magical community
+          in the city.
+          The Salamander Club is a favorite watering hole of the sorcerous set and your best bet to
+          make contact with anyone who might know Mr. Brown.
+          '''
+          active:
+            cantripUp: reqs.gte 6
       ]

     ## The Salamander Club


Order controllers optimized

Order controllers optimized

--- src/controllers/order.coffee
+++ src/controllers/order.coffee
@@ -1,23 +1,25 @@
 app = require process.cwd() + '/app'
 db  = app.get 'models'
+utils = require('sequelize').Utils

 # Order model's CRUD controller.
 module.exports =

   # Lists all orders
   index: (req, res) ->
-    db.Order.findAll()
-      .success (result) ->
-        res.format
-          json: -> res.json result
-          html: -> res.render 'orders', orders: result
+    db.Order.findAll
+        order: ['bid', 'ask']
+      .complete (err, result) ->
+        res.send err if err?
+        output =
+          asks: utils._.where result, bid: null
+          bids: utils._.where result, ask: null
+        res.json output

   # Creates new order with data from `req.body`
   create: (req, res) ->
     db.Order.create req.body
       .success (result) ->
-        if result.ask is 0 then result.ask
-        else delete result.bid
         res.statusCode = 201
         res.send result
       .error (err) ->
@@ -26,42 +28,38 @@

   # Gets order by id
   get: (req, res) ->
-    db.Order.find req.params.id
-      .success (result) ->
-        if not result?
-          res.statusCode = 404
-          res.render '404', 404
+    db.Order.find
+        where:
+          id: req.params.id
+      .complete (err, result) ->
+        if not err?
+          res.send result
         else
-          res.send result
-      .error (err) ->
-        res.statusCode = 500
-        res.send err
+          res.statusCode = 500
+          res.send err

   # Updates order with data from `req.body`
   update: (req, res) ->
     db.Order.update req.body,
         id: req.params.id
-      .complete (err, result) ->
+      .complete (err) ->
         if not err?
           res.statusCode = 204
           res.end()
         else
-          res.statusCode = 500
-          res.send err
+          res.statusCode = 400
+          res.end()

   # Deletes order by id
   delete: (req, res) ->
     db.Order.find
         where:
           id: req.params.id
-      .success (result) ->
-        if not result?
-          res.statusCode = 404
-          res.render '404', 404
-        else
+      .complete (err, result) ->
+        if not err?
           result.destroy().success ->
             res.statusCode = 204
             res.end()
-      .error (err) ->
-        res.statusCode = 500
-        res.send err
+        else
+          res.statusCode = 400
+          res.end()


Added Time Scaling

Added Time Scaling

--- js/main.coffee
+++ js/main.coffee
@@ -17,6 +17,7 @@
   PAN_SPEED = 10
   ROTATE_SPEED = 0.01
   SCALE_SPEED = 1.1
+  TIME_SCALE_SPEED = 1.1

   width = window.innerWidth
   height = window.innerHeight
@@ -46,6 +47,10 @@

   $(window).keydown (e) ->
     e.preventDefault()
+    if e.keyCode == 187
+      timeScale *= TIME_SCALE_SPEED
+    if e.keyCode == 189
+      timeScale /= TIME_SCALE_SPEED
     if e.keyCode == 88
       scale *= SCALE_SPEED
     if e.keyCode == 90


Многострочные строки

Многострочные строки

--- js/main.coffee
+++ js/main.coffee
@@ -1,3 +1,6 @@
 do ->
   x = 1
-  arr = "current number is: #{x}px"+  arr = "current number is: #{x}px"
+
+  arr2= """ current
+            is #{x}"""


+ pass options to encoding methods

+ pass options to encoding methods

--- src/encoding-iterator.coffee
+++ src/encoding-iterator.coffee
@@ -2,6 +2,7 @@
 AbstractIterator      = require("abstract-iterator")
 inherits              = require("abstract-object/lib/util/inherits")
 isArray               = require("abstract-object/lib/util/isArray")
+extend                = require("abstract-object/lib/util/_extend")

 module.exports =  class EncodingIterator
@@ -10,16 +11,18 @@
   encodeOptions: (options)->
     keyEncoding = options.keyEncoding
     if keyEncoding
-      options.lt = keyEncoding.encode(options.lt) if options.lt?
-      options.lte = keyEncoding.encode(options.lte) if options.lte?
-      options.gt = keyEncoding.encode(options.gt) if options.gt?
-      options.gte = keyEncoding.encode(options.gte) if options.gte?
-      options.range = options.range.map keyEncoding.encode.bind(keyEncoding) if isArray options.range
+      options.lt = keyEncoding.encode(options.lt, options) if options.lt?
+      options.lte = keyEncoding.encode(options.lte, options) if options.lte?
+      options.gt = keyEncoding.encode(options.gt, options) if options.gt?
+      options.gte = keyEncoding.encode(options.gte, options) if options.gte?
+      if isArray options.range
+        options.range = options.range.map (item)->
+          keyEncoding.encode item, options
     options
   decodeResult: (result)->
     keyEncoding = @options.keyEncoding
     valueEncoding = @options.valueEncoding
-    result[0] = keyEncoding.decode(result[0]) if result[0]? and keyEncoding
-    result[1] = valueEncoding.decode(result[1]) if result[1]? and valueEncoding
+    result[0] = keyEncoding.decode(result[0], @options) if result[0]? and keyEncoding
+    result[1] = valueEncoding.decode(result[1], @options) if result[1]? and valueEncoding
     result


chore(web): update some build tasks;

chore(web): update some build tasks;

--- apps/actor-web/gulpfile.coffee
+++ apps/actor-web/gulpfile.coffee
@@ -32,9 +32,9 @@
     .pipe connect.reload()

 gulp.task 'html', ->
-  gulp.src ['*.html']
-    .pipe gulp.dest './dist/'
-    .pipe connect.reload()
+#  gulp.src ['*.html']
+#    .pipe gulp.dest './dist/'
+#    .pipe connect.reload()
   gulp.src ['./app/**/*.html']
     .pipe gulp.dest './dist/app/'
     .pipe connect.reload()
@@ -57,8 +57,9 @@
       js: [uglify()]
       css: [autoprefixer(), minifycss()]
     .pipe gulp.dest './dist/'
+    .pipe connect.reload()

-gulp.task 'server', ->
+gulp.task 'server', ['usemin'], ->
   connect.server
     port: 3000
     root: 'dist'


Print status/error codes for unknown HTTP connection issues.

--- src/ext/modules/proxy.coffee
+++ src/ext/modules/proxy.coffee
@@ -6,6 +6,16 @@
       url: url
       success: (data, status, xhr) -> go null, data
       error: (xhr, status, error) -> go new Flow.Error error
+
+  optsToString = (opts) ->
+    if opts?
+      str = " with opts #{ JSON.stringify opts }"
+      if str.length > 50
+        "#{ str.substr 0, 50 }..."
+      else
+        str
+    else
+      ''

   http = (method, path, opts, go) ->
     _.status 'server', 'request', path
@@ -49,14 +59,10 @@
         serverError
       else if error?.message
         new Flow.Error error.message
-      else if status is 0
-        new Flow.Error 'Could not connect to H2O'
-      else if isString error
-        new Flow.Error error
-      else
-        new Flow.Error 'Unknown error'
-
-      go new Flow.Error "Error calling #{method} #{path} with opts #{JSON.stringify opts}", cause
+      else
+        new Flow.Error "HTTP connection failure: status=#{status}, code=#{xhr.status}, error=#{error or '?'}"
+
+      go new Flow.Error "Error calling #{method} #{path}#{optsToString opts}", cause

   doGet = (path, go) -> http 'GET', path, null, go
   doPost = (path, opts, go) -> http 'POST', path, opts, go


create array in range

create array in range

--- js/main.coffee
+++ js/main.coffee
@@ -1,7 +1,2 @@
 do ->
-  x = on
-  y = yes
-  z = true
-  console.log(x)
-  console.log(y)
-  console.log(z)+  console.log x = [9...2]


coffee configurator

coffee configurator

--- js/main.coffee
+++ js/main.coffee
@@ -1,13 +1,24 @@
-do ->
-  createConfigurator = ->
-    configurator = (fieldName, value) ->
-      obj[fieldName] = value
-      return configurator
-
-    configurator.result = obj = {}
-
-    return configurator
+do =>
+  limited = (time, func) ->

-  _ = createConfigurator()
-  console.log _("age", 25)("name", "sergii").result
+    isCalled = no
+    func = time and time = 20 if time?()

+    ->
+      @args = arguments
+      if not isCalled
+        isCalled = yes
+        setTimeout((=>
+          func.apply(@, @args)
+          isCalled = no
+          this),
+          time)
+      this
+
+  searchFriend = limited(500, (name)->console.log name + "found")
+  searchFriend (num) for num in [1...10]
+
+  document.getElementById("search-friend").addEventListener("keyup", limited(2000, -> console.log @value))
+  this
+
+


Removed unnecessary subscription.

Removed unnecessary subscription.

--- client/client.coffee
+++ client/client.coffee
@@ -1,5 +1,4 @@
 # Subscribe
-Meteor.subscribe("users");
 Meteor.subscribe("posts");
 Meteor.subscribe("categories");
 Meteor.subscribe("allUserData");


made "Restart All Threads" work again

made "Restart All Threads" work again

(the green button in the debugger)

--- client/keymap.coffee
+++ client/keymap.coffee
@@ -199,6 +199,7 @@

 createCommand = (xx) -> CodeMirror.commands[xx] ?= (cm) -> (if (h = cm.dyalogCommands) && h[xx] then h[xx]()); return
 createCommand 'CBP'
+createCommand 'MA'

 '''
   [     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F]


remove code relict; #290

remove code relict; #290

--- app/assets/javascripts/admin/views/tasktype/task_type_item_view.coffee
+++ app/assets/javascripts/admin/views/tasktype/task_type_item_view.coffee
@@ -48,9 +48,7 @@

-

-
-

+


Improved error handling.

Improved error handling.

--- app/assets/javascripts/app/models/user.js.coffee
+++ app/assets/javascripts/app/models/user.js.coffee
@@ -37,16 +37,20 @@
     "user icon"

   initials: ->
-    if @firstname[0] && @lastname[0]
-      @firstname[0] + @lastname[0]
-    else if @firstname[0] && !@lastname[0]
-      @firstname[0] + @firstname[1]
-    else if !@firstname[0] && @lastname[0]
-      @lastname[0] + @lastname[1]
+    if @firstname && @lastname && @firstname[0] && @lastname[0]
+      return @firstname[0] + @lastname[0]
+    else if @firstname && @firstname[0] && !@lastname
+      if @firstname[1]
+        return @firstname[0] + @firstname[1]
+      return @firstname[0]
+    else if !@firstname && @lastname && @lastname[0]
+      if @lastname[1]
+        return @lastname[0] + @lastname[1]
+      return @lastname[0]
     else if @email
-      @email[0] + @email[1]
+      return @email[0] + @email[1]
     else
-      '??'
+      return '??'

   avatar: (big = false, placement = '', cssClass = '') ->
     if big


Added Nico + Sven to credits

Added Nico + Sven to credits

--- app/assets/javascripts/views/credits_view.coffee
+++ app/assets/javascripts/views/credits_view.coffee
@@ -36,6 +36,8 @@

Thomas Werkmeister

Daniel Werner

Georg Wiese

+
Sven Mischkewitz

+
Nico Ring


Remove classification.update from survey task

--- app/classifier/tasks/survey/annotation-view.cjsx
+++ app/classifier/tasks/survey/annotation-view.cjsx
@@ -32,4 +32,4 @@

   handleRemove: (index) ->
     @props.annotation.value.splice index, 1
-    @props.classification.update 'annotations'
+    @props.onChange @props.annotation


Do not show starter licenses to Belgians (part 2)

Forgot to also handle CoursesNotAssignedModal.

--- app/views/courses/CoursesNotAssignedModal.coffee
+++ app/views/courses/CoursesNotAssignedModal.coffee
@@ -15,5 +15,5 @@
     })
     if options.courseID in STARTER_LICENSE_COURSE_IDS
       @supermodel.trackRequest(me.getLeadPriority())
-        .then(({ priority }) => @state.set({ promoteStarterLicenses: (priority is 'low') }))
+        .then(({ priority }) => @state.set({ promoteStarterLicenses: (priority is 'low') and (me.get('preferredLanguage') isnt 'nl-BE')}))
     @listenTo @state, 'change', @render


fix no sharedClassroom case

fix no sharedClassroom case


increase timeout, api is now taking care of this

--- assets/scripts/app/auth.coffee
+++ assets/scripts/app/auth.coffee
@@ -1,6 +1,6 @@
 @Travis.Auth = Ember.Object.extend
   iframe: $('<iframe id="auth-frame" />').hide()
-  timeout: 10000
+  timeout: 30000 # api has a lower timeout for opening a popup
   state: 'signed-out'
   receivingEnd: "#{location.protocol}//#{location.host}"


Fixed bug with resolving local ip

Fixed bug with resolving local ip

--- cli/utils.coffee
+++ cli/utils.coffee
@@ -102,7 +102,7 @@
     out = try childProcess.execSync cmd, stdio: 'pipe'
     out ?= try childProcess.execSync 'ipconfig getifaddr en0', stdio: 'pipe'
     if out
-        String(out).trim()
+        String(out).split('\n')[0].trim()
     else
         log.warn "Cannot resolve local IP address; is ifconfig or ipconfig commands available?"
         ''


Show HUD message for mute command.

Show HUD message for mute command.

Fixes #3192.

--- background_scripts/main.coffee
+++ background_scripts/main.coffee
@@ -138,10 +138,16 @@
           tabs = (tab for tab in tabs when tab.id != currentTab.id)
         audibleUnmutedTabs = (tab for tab in tabs when tab.audible and not tab.mutedInfo.muted)
         if 0 < audibleUnmutedTabs.length
+          chrome.tabs.sendMessage tabId, {frameId, name: "showMessage", message: "Muting #{audibleUnmutedTabs.length} tab(s)."}
           muteTab tab for tab in audibleUnmutedTabs
         else
+          chrome.tabs.sendMessage tabId, {frameId, name: "showMessage", message: "Unmuting all muted tabs."}
           muteTab tab for tab in tabs when tab.mutedInfo.muted
     else
+      if currentTab.mutedInfo.muted
+        chrome.tabs.sendMessage tabId, {frameId, name: "showMessage", message: "Unmuted tab."}
+      else
+        chrome.tabs.sendMessage tabId, {frameId, name: "showMessage", message: "Muted tab."}
       muteTab currentTab

 #


Remove custom load semantics

Remove custom load semantics

--- scripts/models/content/module.coffee
+++ scripts/models/content/module.coffee
@@ -26,14 +26,6 @@
       # Default language for new content is the browser's language
       language: navigator?.language or navigator?.userLanguage or 'en'

-    load: () ->
-      if not @_loading
-        @_loading = @fetch()
-        @_loading.done () =>
-          @trigger('loaded')
-          @loaded = true
-      @_loading
-
     # Begin editing this medium as soon as it is added
     addAction: () ->
       id = @id or @cid


Update numericable.coffee

Update numericable.coffee

Increase date delta

--- server/konnectors/numericable.coffee
+++ server/konnectors/numericable.coffee
@@ -49,7 +49,7 @@
                 log: log
                 model: Bill
                 identifier: 'numericable'
-                dateDelta: 4
+                dateDelta: 12
             )
             .args(requiredFields, {}, {})
             .fetch (err, fields, entries) ->


Explicitly fall back to hide Vomnibar completions

--- pages/vomnibar.coffee
+++ pages/vomnibar.coffee
@@ -61,7 +61,7 @@
     @reset()

   reset: ->
-    @completionList.style.display = "none"
+    @completionList.style.display = ""
     @input.value = ""
     @updateTimer = null
     @completions = []
@@ -151,7 +151,7 @@
   populateUiWithCompletions: (completions) ->
     # update completion list with the new data
     @completionList.innerHTML = completions.map((completion) -> "<li>#{completion.html}</li>").join("")
-    @completionList.style.display = if completions.length > 0 then "block" else "none"
+    @completionList.style.display = if completions.length > 0 then "block" else ""
     @selection = Math.min(Math.max(@initialSelectionValue, @selection), @completions.length - 1)
     @updateSelection()

@@ -181,7 +181,7 @@
     @input.addEventListener "input", @update
     @input.addEventListener "keydown", @onKeydown
     @completionList = @box.querySelector("ul")
-    @completionList.style.display = "none"
+    @completionList.style.display = ""

     window.addEventListener "focus", => @input.focus()


options is not always set

options is not always set

--- lib/generators/nas_extjs/templates/public/app/model/Base.coffee
+++ lib/generators/nas_extjs/templates/public/app/model/Base.coffee
@@ -47,7 +47,7 @@

         , this )

-    save: ( options )->
+    save: ( options={} )->
         if options.syncAssociations
             for opt in options.syncAssociations
                 opt = Ext.Object.getKeys(opt)[0] if Ext.isObject( opt )


Revert "add ab tests for home button"

Revert "add ab tests for home button"

This reverts commit d9c43403f18cbcab5d508a2c493683fa285d51e2.

--- js/ab_test_definitions.coffee
+++ js/ab_test_definitions.coffee
@@ -9,4 +9,3 @@
 exports.ab_test_definitions =
   a_is_a: [true, false]
   split_form: [true, false]
-  button_copy: [true, false]


don't need the extra tracking

don't need the extra tracking

--- resources/assets/lib/play-detail-menu.coffee
+++ resources/assets/lib/play-detail-menu.coffee
@@ -35,7 +35,6 @@

     @body = document.body
     @portal = document.createElement('div') if props.usePortal
-    @portalAdded = false

     @state =
       active: false
@@ -91,15 +90,13 @@

   addPortal: =>
-    if @portal? && !@portalAdded
+    if @portal? && !@portal.parentElement?
       @body.appendChild @portal
-      @portalAdded = true

   removePortal: =>
-    if @portal? && @portalAdded
+    if @portal? && @portal.parentElement?
       @body.removeChild @portal
-      @portalAdded = false

   render: =>


Fix incorrect loaded state marker

Fix incorrect loaded state marker

Delete loaded marker right before first boot.

Turbolinks.controller.advanceHistory doesn't trigger before-cache anymore so it saves page with loaded state still set.

--- resources/assets/lib/react-turbolinks.coffee
+++ resources/assets/lib/react-turbolinks.coffee
@@ -26,6 +26,7 @@
     $(document).on 'turbolinks:load', =>
       # Delayed to wait until cacheSnapshot finishes.
       Timeout.set 1, =>
+        @deleteLoadedMarker()
         @destroyPersisted()
         @documentReady = true
         @boot()
@@ -34,23 +35,32 @@
       @destroy()

+  allTargets: (callback) =>
+    for own name, component of @components
+      for target in component.targets
+        callback({ name, component, target })
+
+
   boot: =>
     return unless @documentReady

-    for own _name, component of @components
-      for target in component.targets
-        continue if target.dataset.reactTurbolinksLoaded == '1'
-        target.dataset.reactTurbolinksLoaded = '1'
-        @targets.push target
-        ReactDOM.render React.createElement(component.element, component.propsFunction(target)), target
+    @allTargets ({ target, component }) =>
+      return if target.dataset.reactTurbolinksLoaded == '1'
+
+      target.dataset.reactTurbolinksLoaded = '1'
+      @targets.push target
+      ReactDOM.render React.createElement(component.element, component.propsFunction(target)), target
+
+
+  deleteLoadedMarker: =>
+    @allTargets ({ target }) =>
+      delete target.dataset.reactTurbolinksLoaded

   destroy: =>
-    for own _name, component of @components
-      for target in component.targets
-        continue if target.dataset.reactTurbolinksLoaded != '1'
-        target.dataset.reactTurbolinksLoaded = null
-        ReactDOM.unmountComponentAtNode target if !component.persistent
+    @allTargets ({ target, component }) =>
+      if target.dataset.reactTurbolinksLoaded == '1' && !component.persistent
+        ReactDOM.unmountComponentAtNode target

   destroyPersisted: =>


Unregister frame when postMessage fails.

--- background_scripts/main.coffee
+++ background_scripts/main.coffee
@@ -357,7 +357,11 @@

   sendMessage: (messageType, tabId, request = {}) ->
     extend request, {handler: "linkHintsMessage", messageType}
-    port.postMessage request for own _, port of @tabState[tabId].ports
+    for own frameId, port of @tabState[tabId].ports
+      try
+        port.postMessage request
+      catch
+        @unregisterFrame tabId, frameId

   prepareToActivateMode: (tabId, originatingFrameId, {modeIndex}) ->
     @tabState[tabId] = {frameIds: frameIdsForTab[tabId][..], hintDescriptors: [], originatingFrameId, modeIndex}


Note that createTab/pages/blank.html doesn't work in incognito mode.

--- background_scripts/main.coffee
+++ background_scripts/main.coffee
@@ -247,6 +247,8 @@
 BackgroundCommands =
   createTab: (callback) ->
     url = Settings.get "newTabUrl"
+    # FIXME(smblott).  "pages/blank.html" doesn't work in incognito mode. It opens the tab in a
+    # non-incognito-mode window.  Perhaps we should just use "chrome://newtab" in that case?
     url = chrome.runtime.getURL url if url == "pages/blank.html"
     openUrlInNewTab { url }, callback
   duplicateTab: (callback) ->


Update inline-docs on has-many js

Update inline-docs on has-many js

[skip ci]

--- app/assets/javascripts/active_admin/components/has_many.js.coffee
+++ app/assets/javascripts/active_admin/components/has_many.js.coffee
@@ -2,7 +2,7 @@
   # Provides a before-removal hook:
   # $ ->
   #   # This is a good place to tear down JS plugins to prevent memory leaks.
-  #   $(document).on 'has_many_remove:before', '.has_many', (e, fieldset)->
+  #   $(document).on 'has_many_remove:before', '.has_many_container', (e, fieldset)->
   #     fieldset.find('.select2').select2 'destroy'
   #
   $(document).on 'click', 'a.button.has_many_remove', (e)->
@@ -16,13 +16,13 @@
   # Provides before and after creation hooks:
   # $ ->
   #   # The before hook allows you to prevent the creation of new records.
-  #   $(document).on 'has_many_add:before', '.has_many', (e)->
+  #   $(document).on 'has_many_add:before', '.has_many_container', (e)->
   #     if $(@).children('fieldset').length >= 3
   #       alert "you've reached the maximum number of items"
   #       e.preventDefault()
   #
   #   # The after hook is a good place to initialize JS plugins and the like.
-  #   $(document).on 'has_many_add:after', '.has_many', (e, fieldset)->
+  #   $(document).on 'has_many_add:after', '.has_many_container', (e, fieldset)->
   #     fieldset.find('select').chosen()
   #
   $(document).on 'click', 'a.button.has_many_add', (e)->


cleanup followable

cleanup followable

--- apps/personalize/client/mixins/followable.coffee
+++ apps/personalize/client/mixins/followable.coffee
@@ -36,11 +36,11 @@
     @followed.unshift model.toJSON()
     @following.follow model.id, { notes: 'Followed from /personalize' }

-    analytics.track.click @analyticsFollowMessage, label: analytics.modelNameAndIdToLabel(model.get('display_model'), @model.get('id'))
+    analytics.track.click @analyticsFollowMessage, label: analytics.modelNameAndIdToLabel(model.get('display_model'), model.get('id'))

   unfollow: (e) ->
     id      = $(e.currentTarget).data 'id'
     model   = @followed.remove id
     @following.unfollow id

-    analytics.track.click @analyticsUnfollowMessage, label: analytics.modelNameAndIdToLabel(model.get('display_model'), @model.get('id'))
+    analytics.track.click @analyticsUnfollowMessage, label: analytics.modelNameAndIdToLabel(model.get('display_model'), model.get('id'))


Update description formula per Madeline's request

--- apps/sitemaps/routes.coffee
+++ apps/sitemaps/routes.coffee
@@ -171,10 +171,10 @@
       "contentUrl": artwork.imageUrl()
       "name": artwork.get('title')
       "description": "
-        #{artwork.get('title')} is a work of art created
-        #{if name = artwork.related().artist.get('name') then " by #{name}" else ''}
-        #{if date = artwork.get('date') then "in #{date}. " else '. '}
-        #{if med = artwork.get('medium') then "The medium is #{med.toLowerCase()}" else ''}.
+        #{if title = artwork.get('title') then "#{title}" else "This work"}
+        #{if name = artwork.related().artist.get('name') then "was created by #{name}" else if maker = artwork.get('cultural_maker') then "was created by #{maker}" else ''}
+        #{if date = artwork.get('date') then "in #{date}." else '. '}
+        #{if institution = artwork.get('collecting_institution') != "" then "This work was exhibited at #{institution}." else "This work was exhibited at #{artwork.related().partner.get('name')}."}
       "
       "encodingFormat": "jpeg"
       "keywords": artwork.toPageDescription().split(', ')


[LoadingFree] lowercase the feedId

[LoadingFree] lowercase the feedId

--- client/app/Applications/Topics.kdapplication/AppController.coffee
+++ client/app/Applications/Topics.kdapplication/AppController.coffee
@@ -24,7 +24,7 @@
   createFeed:(view, loadFeed = no)->
     {JTag} = KD.remote.api
     KD.getSingleton("appManager").tell 'Feeder', 'createContentFeedController', {
-      feedId                : 'Topics.main'
+      feedId                : 'topics.main'
       itemClass             : @listItemClass
       limitPerPage          : 20
       useHeaderNav          : yes


Set broken specs to pending

Set broken specs to pending

--- test/components/task-plan/footer.spec.coffee
+++ test/components/task-plan/footer.spec.coffee
@@ -76,7 +76,7 @@
     expect(node.querySelector('.-publish')).to.not.be.null
     expect(node.querySelector('.-select-problems')).to.be.null

-  it 'should have correct buttons when reading is visible', ->
+  xit 'should have correct buttons when reading is visible', ->
     node = helper(VISIBLE_READING)

     expect(node.querySelector('.delete-link')).to.be.null
@@ -96,8 +96,6 @@
     node = helper(HW_WITH_EXERCISES)
     expect(node.querySelector('.-select-problems')).to.be.null

-  it 'should not show select problems when homework is visible', ->
+  xit 'should not show select problems when homework is visible', ->
     node = helper(VISIBLE_HW)
     expect(node.querySelector('.-select-problems')).to.be.null
-
-


Scrollable feed

Scrollable feed

--- coffee/routes.coffee
+++ coffee/routes.coffee
@@ -18,7 +18,7 @@
     match "top", "posts#show", params:
       id: "today", title: "Топ 20 постов за сегодня", scrollable: false
     match "feed", "posts#show", params:
-      id: "feed", title: "Подписки", scrollable: false
+      id: "feed", title: "Подписки"

     match "u/:user", "posts#show", params:
       show: "messages"


redirect to home page after deleting a team

so we don't need to style the team list before opening registration

--- controllers/teams.coffee
+++ controllers/teams.coffee
@@ -172,4 +172,4 @@
 app.delete '/teams/:id', [m.loadTeam, m.ensureAccess], (req, res, next) ->
   req.team.remove (err) ->
     return next err if err
-    res.redirect '/teams'
+    res.redirect '/'


OX-120 priorityOffset fix

OX-120 priorityOffset fix

--- app/assets/javascripts/model/binary.coffee
+++ app/assets/javascripts/model/binary.coffee
@@ -153,7 +153,8 @@
       zoomedPositionBucket = [positionBucket[0] >> zoomSteps[0], positionBucket[1] >> zoomSteps[0], positionBucket[2] >> zoomSteps[0]]

-      resizeRadius = 5
+      resizeRadius = 4
+      priorityOffset = (256 - (resizeRadius << 1)*(resizeRadius << 1)) / 2

       buckets  = @getBucketArray(zoomedPositionBucket, resizeRadius, resizeRadius, 0).concat(
                   @getBucketArray(zoomedPositionBucket, resizeRadius, 0, resizeRadius),
@@ -200,7 +201,7 @@
         index--
         if buckets[index]
           # priority = Math.max(Math.abs(buckets[index][0] - @positionBucket[0]), Math.abs(buckets[index][1] - @positionBucket[1]), Math.abs(buckets[index][2] - @positionBucket3[2]))
-          PullQueue.insert [buckets[index][0] + direction_x, buckets[index][1] + direction_y, buckets[index][2] + direction_z], zoomSteps[0], @PRIORITIES[index % @PRIORITIES.length] + @PRELOADING[level]
+          PullQueue.insert [buckets[index][0] + direction_x, buckets[index][1] + direction_y, buckets[index][2] + direction_z], zoomSteps[0], @PRIORITIES[priorityOffset + index % @PRIORITIES.length] + @PRELOADING[level]

         unless i % buckets.length
           index = buckets.length


header export compatible with firefox

header export compatible with firefox

--- app/assets/javascripts/table-export.coffee
+++ app/assets/javascripts/table-export.coffee
@@ -6,7 +6,7 @@
   dt = $("#" + table_selector).dataTable()
   row_data = dt.fnSettings().aoData
   headers = dt.fnSettings().aoHeader[0].map (c) ->
-    c.cell.innerText.trim()
+    $(c.cell).text().trim()
   .join("%09")
   tsv = row_data.map (row) ->
     row._aData.map (cell) ->


Remove classification.update from crop task

--- app/classifier/tasks/crop/initializer.cjsx
+++ app/classifier/tasks/crop/initializer.cjsx
@@ -42,7 +42,7 @@
     {x, y} = @props.getEventOffset e
     _start = {x, y}
     @props.annotation.value = {x, y, width: 0, height: 0, _start}
-    @props.classification.update 'annotation'
+    @props.onChange @props.annotation

   handleInitDrag: (e) ->
     {x, y} = @props.getEventOffset e
@@ -53,7 +53,7 @@
     @props.annotation.value.y = Math.min _start.y, y
     @props.annotation.value.width = Math.abs _start.x - x
     @props.annotation.value.height = Math.abs _start.y - y
-    @props.classification.update 'annotation'
+    @props.onChange @props.annotation

   handleBoxDrag: (e, d) ->
     difference = @props.normalizeDifference(e, d)
@@ -61,7 +61,7 @@
     maxY = (@props.containerRect.height / @props.scale.vertical) - @props.annotation.value.height
     @props.annotation.value.x = Math.max 0, Math.min maxX, @props.annotation.value.x += difference.x
     @props.annotation.value.y = Math.max 0, Math.min maxY, @props.annotation.value.y += difference.y
-    @props.classification.update 'annotations'
+    @props.onChange @props.annotation

   handleStartHandle: (e) ->
     mouse = @props.getEventOffset e
@@ -78,7 +78,7 @@
     diff = _start.mouse[coord] - mouse[coord]
     @props.annotation.value[coord] = Math.min _start.mouse[coord] + _start.rect[dimension], mouse[coord]
     @props.annotation.value[dimension] = Math.abs _start.rect[dimension] + diff
-    @props.classification.update 'annotation'
+    @props.onChange @props.annotation

   handleDragFar: (coord, e) ->
     dimension = {x: 'width', y: 'height'}[coord]
@@ -89,4 +89,4 @@
     diff = _start.mouse[coord] - mouse[coord]
     @props.annotation.value[coord] = Math.min _start.rect[coord], mouse[coord]
     @props.annotation.value[dimension] = Math.abs _start.rect[dimension] - diff
-    @props.classification.update 'annotation'
+    @props.onChange @props.annotation


Add on new song submit handler.

Add on new song submit handler.

--- app/client/js/songs/edit/react/page.coffee
+++ app/client/js/songs/edit/react/page.coffee
@@ -9,22 +9,26 @@
     @constructor
   ###
   constructor: (routes) ->
-    {div,form,input,textarea,a} = React.DOM
+    {div,form,input,textarea,button,a} = React.DOM

     @create = React.createClass

       render: ->
         div className: 'new-song',
-          form null,
+          form onSubmit: @onFormSubmit,
             input
               autoFocus: true
               name: 'name'
               placeholder: Page.MSG_SONG_NAME
+              ref: 'name'
               type: 'text'
             textarea
               name: 'chordpro'
               placeholder: Page.MSG_WRITE_LYRICS_HERE
               ref: 'chordpro'
+            button
+              type: 'submit'
+            , Page.MSG_CREATE_NEW_SONG
           a
             href: 'http://linkesoft.com/songbook/chordproformat.html'
             target: '_blank'
@@ -37,6 +41,11 @@
       componentWillUnmount: ->
         @chordproTextarea_.dispose()

+      onFormSubmit: (e) ->
+        e.preventDefault()
+        @refs['name'].getDOMNode().focus()
+
   @MSG_SONG_NAME: goog.getMsg 'Song name'
   @MSG_WRITE_LYRICS_HERE: goog.getMsg 'Write lyrics here'
+  @MSG_CREATE_NEW_SONG: goog.getMsg 'Create new song'
   @MSG_HOW_TO_WRITE_LYRICS: goog.getMsg 'How to write lyrics'


Remove defunct _test directory

Remove defunct _test directory

--- _test/test.coffee
+++ _test/test.coffee
@@ -1,3 +0,0 @@
-assert = require 'assert'
-
-it("test mocha", () -> assert.equal(1, 1))


fix gfm autocomplete for usernames

fix gfm autocomplete for usernames

--- app/assets/javascripts/gfm_auto_complete.js.coffee
+++ app/assets/javascripts/gfm_auto_complete.js.coffee
@@ -1,52 +1,58 @@
 # Creates the variables for setting up GFM auto-completion

 window.GitLab ?= {}
-GitLab.GfmAutoComplete ?= {}
-
-# Emoji
-data      = []
-template  = "
${name}
"
-GitLab.GfmAutoComplete.Emoji = {data, template}
-
-# Team Members
-data      = []
-url     = '';
-params  = {private_token: '', page: 1}
-GitLab.GfmAutoComplete.Members = {data, url, params}
-
-# Add GFM auto-completion to all input fields, that accept GFM input.
-GitLab.GfmAutoComplete.setup = ->
-  input = $('.js-gfm-input')
-
+GitLab.GfmAutoComplete =
   # Emoji
-  input.atWho ':',
-    data: GitLab.GfmAutoComplete.Emoji.data,
-    tpl: GitLab.GfmAutoComplete.Emoji.template
+  Emoji:
+    data: []
+    template: '
${name}
'

   # Team Members
-  input.atWho '@', (query, callback) ->
-    (getMoreMembers = ->
-      $.getJSON(GitLab.GfmAutoComplete.Members.url, GitLab.GfmAutoComplete.Members.params)
-        .success (members) ->
-          # pick the data we need
-          newMembersData = $.map(members, (m) -> m.name )
+  Members:
+    data: []
+    url: ''
+    params:
+      private_token: ''
+      page: 1
+    template: '
${username} ${name}
'

-          # add the new page of data to the rest
-          $.merge(GitLab.GfmAutoComplete.Members.data, newMembersData)
+  # Add GFM auto-completion to all input fields, that accept GFM input.
+  setup: ->
+    input = $('.js-gfm-input')

-          # show the pop-up with a copy of the current data
-          callback(GitLab.GfmAutoComplete.Members.data[..])
+    # Emoji
+    input.atWho ':',
+      data: @Emoji.data
+      tpl: @Emoji.template

-          # are we past the last page?
-          if newMembersData.length is 0
-            # set static data and stop callbacks
-            input.atWho '@',
-              data: GitLab.GfmAutoComplete.Members.data
-              callback: null
-          else
-            # get next page
-            getMoreMembers()
+    # Team Members
+    input.atWho '@',
+      tpl: @Members.template
+      callback: (query, callback) =>
+        (getMoreMembers = =>
+          $.getJSON(@Members.url, @Members.params).done (members) =>
+            # pick the data we need
+            newMembersData = $.map(members, (m) ->
+              username: m.username
+              name: m.name
+            )

-      # so the next request gets the next page
-      GitLab.GfmAutoComplete.Members.params.page += 1
-    ).call()
+            # add the new page of data to the rest
+            $.merge(@Members.data, newMembersData)
+
+            # show the pop-up with a copy of the current data
+            callback(@Members.data[..])
+
+            # are we past the last page?
+            if newMembersData.length is 0
+              # set static data and stop callbacks
+              input.atWho '@',
+                data: @Members.data
+                callback: null
+            else
+              # get next page
+              getMoreMembers()
+
+          # so the next callback requests the next page
+          @Members.params.page += 1
+        ).call()


don't save clean agents

don't save clean agents

--- app/assets/javascripts/mixins/agent_form.js.coffee
+++ app/assets/javascripts/mixins/agent_form.js.coffee
@@ -8,13 +8,13 @@

   actions:
-
     noop: ->
       false

     safeRecord: ->
-      @validateForm()
-      Ember.run.next @, @submitForm
+      if @get('dirty')
+        @validateForm()
+        Ember.run.next @, @submitForm
       false

     cancelChanges: ->


LitePapers don't `belongTo` flows.

LitePapers don't `belongTo` flows.

Things really only can belong to one thing at a time now.

--- app/assets/javascripts/models/lite_paper.js.coffee
+++ app/assets/javascripts/models/lite_paper.js.coffee
@@ -1,7 +1,6 @@
 a = DS.attr
 ETahi.LitePaper = DS.Model.extend
   paper: DS.belongsTo('paper')
-  flow: DS.belongsTo('flow')

   title: a('string')
   shortTitle: a('string')


bcarousel comment

bcarousel comment

--- app/assets/javascripts/plugins/bcarousel.js.coffee
+++ app/assets/javascripts/plugins/bcarousel.js.coffee
@@ -1,4 +1,6 @@
 # Carousel based on twitter-bootstrap
+# @creator: Boris Barroso
+# @email: boriscyber@gmail.com
 class Bcarousel
   constructor: (@container, @width)->
     @$container = $(@container)


fix duty.directive test

fix duty.directive test

--- app/modules/home/duties/duty.directive.spec.coffee
+++ app/modules/home/duties/duty.directive.spec.coffee
@@ -14,6 +14,11 @@
             resolve: sinon.stub()
         }
         provide.value "$tgNavUrls", mockTgNavUrls
+
+    _mockTranslateFilter = () ->
+        mockTranslateFilter = (value) ->
+            return value
+        provide.value "translateFilter", mockTranslateFilter

     _mockTgProjectsService = () ->
         mockTgProjectsService = {
@@ -35,6 +40,7 @@
             _mockTgNavUrls()
             _mockTgProjectsService()
             _mockTranslate()
+            _mockTranslateFilter()
             return null

     beforeEach ->


add stub symbol

add stub symbol

--- apps/artwork_2/components/auction/test/view.coffee
+++ apps/artwork_2/components/auction/test/view.coffee
@@ -33,6 +33,7 @@
           estimate: '$7,000–$9,000'
           current_bid: amount: '$55,000'
           counts: bidder_positions: 19
+          symbol: '$'
           minimum_next_bid:
             amount: '$60,000'
             cents: 6000000


removed verifytokenhandlerhelper from testhelper/index

--- servers/testhelper/index.coffee
+++ servers/testhelper/index.coffee
@@ -100,35 +100,6 @@

 class ValidationHandlerHelper
-
-  @generateVerifyTokenRequestBody = (opts = {}) ->
-
-    defaultBodyObject =
-      token : ''
-
-    deepObjectExtend defaultBodyObject, opts
-
-    return defaultBodyObject
-
-
-  @generateVerifyTokenRequestParams = (opts = {}) ->
-
-    { token } = opts
-    delete opts.token
-
-    url  = generateUrl
-      route : "Verify/#{token}"
-
-    body = ValidationHandlerHelper.generateVerifyTokenRequestBody()
-
-    params               = { url, body }
-    defaultRequestParams = generateDefaultRequestParams params
-    requestParams        = deepObjectExtend defaultRequestParams, opts
-    # after deep extending object, encodes body param to a query string
-    requestParams.body   = querystring.stringify requestParams.body
-
-    return requestParams
-

   @generateValidateRequestBody = (opts = {}) ->


Replace an error with a graph

Replace an error with a graph

--- scripts/rc.coffee
+++ scripts/rc.coffee
@@ -6,6 +6,7 @@
 Url = require 'url'
 prettyMs = require 'pretty-ms'
 wolfram = require 'wolfram'
+sparkline = require 'sparkline'

 ## Config
 ##
@@ -62,7 +63,18 @@
             return msg.reply "Recent RCs for #{who}: #{recent}, latest from #{prettyMs age} total of #{self.recent.length} in the last #{prettyMs interval}"
           return msg.reply "There wasn't enough data :("
       else if options.match /graph/
-        throw RCError("TODO(sshirokov): Spark graph time for #{who}")
+        new RCScore(who).fetch_recent start, (err, self) =>
+          return msg.reply "That fucking blew up: #{err}" if err
+          return msg.reply "Can't draw with nothing ;(" if not self.recent.length
+
+          if self.recent.length
+            first = self.recent[0]
+            latest = self.recent[..].pop()
+            age = Date.now() - latest.timestamp
+            span = latest.timestamp - first.timestamp
+            recent = (parseFloat(s.score) for s in self.recent[-140...]).filter (score) ->
+              not isNaN(score)
+            return msg.reply "#{@who} #{sparkline recent} - Spans #{prettyMs span}, latest #{prettyMs age} old"
       else
         return msg.reply "What the fuck does #{options} even mean?"


Clean up documentation

Clean up documentation

--- tapestry-core/src/main/coffeescript/META-INF/modules/core/pubsub.coffee
+++ tapestry-core/src/main/coffeescript/META-INF/modules/core/pubsub.coffee
@@ -12,140 +12,147 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.

+# ## core/pubsub
+#
 # Framework/application publish and subscribe that is independent of
 # the DOM. Parts of this are modelled on how jQuery DOM events work.
+define ["_"],
+  (_) ->

-define ["_"], (_) ->
+    exports = {}

-  exports = {}
+    subscribers = { }

-  subscribers = { }
+    kullSubs = (name, namespaces, responder) ->
+      list = subscribers[name]
+      return if list is null

-  kullSubs = (name, namespaces, responder) ->
-    list = subscribers[name]
-    return if list is null
+      # Work backwards to avoid excessive copies
+      for i in [list.length - 1 .. 0]
+        subscriber = list[i]
+        # TODO: _.intersection is expensive
+        if (!responder or subscriber.fn is responder) and
+           (namespaces.length == 0 or _.intersection(namespaces, subscriber.namespaces).length > 0)
+          if list.iterating
+            subscribers[name] = list = list[..]
+          list.splice i, 1

-    # Work backwards to avoid excessive copies
-    for i in [list.length - 1 .. 0]
-      subscriber = list[i]
-      # TODO: _.intersection is expensive
-      if (!responder or subscriber.fn is responder) and
-         (namespaces.length == 0 or _.intersection(namespaces, subscriber.namespaces).length > 0)
+      return
+
+    addSub = (stimulusName, addFirst, responder) ->
+      [simpleName, namespaces...] = stimulusName.split '.'
+
+      subscriber =
+        stimulus: simpleName
+        namespaces: namespaces
+        fn: responder
+
+      list = subscribers[simpleName]
+
+      if not list
+        subscribers[simpleName] = [subscriber]
+      else
+        # If iterating the list (during a publish), then do a copy-on-write.
+        # This allows a clean way to have listeners unsubscribe one first notification, or
+        # otherwise change the subscriptions.
         if list.iterating
-          subscribers[name] = list = list[..]
-        list.splice i, 1
+          subscribers[simpleName] = list = list.slice[..]

-    return
+        list[if addFirst then "unshift" else "push"] subscriber

-  addSub = (stimulusName, addFirst, responder) ->
-    [simpleName, namespaces...] = stimulusName.split '.'
+      return

-    subscriber =
-      stimulus: simpleName
-      namespaces: namespaces
-      fn: responder
+    # Adds a responder for a stimulus.  The stimulus name consists of a simple topic name
+    # (used when publishing a message), and optional set of namespaces; each namespace
+    # is preceded by a '.'.  The namespaces make it easier to identify specific responders
+    # later, such as when removing a responder.
+    # The ordering identifies where the listener will be placed.
+    # The listenerfn is a function to be invoked via the publisher. A topic publisher
+    # will publish a message with an application-specific memo.  The listenerfn receives
+    # the memo parameter, and an event parameter.  The event parameter allows the
+    # message to be terminated early.
+    #
+    # * stimulus - name of stimulus to respond to, with namespaces appended
+    # * responder - function to be invoked when the stimulus is fired. The responder
+    # is passed a memo object, and an event. The event can be used to cancel or
+    # pause the stimulus.
+    #
+    # Returns this module's exports, for easy chaining of calls.
+    exports.respondTo = exports.on = (stimulusName, responder) ->

-    list = subscribers[simpleName]
+      addSub stimulusName, false, responder

-    if not list
-      subscribers[simpleName] = [subscriber]
-    else
-      # If iterating the list (during a publish), then do a copy-on-write.
-      # This allows a clean way to have listeners unsubscribe one first notification, or
-      # otherwise change the subscriptions.
-      if list.iterating
-        subscribers[simpleName] = list = list.slice[..]
+      return exports

-      list[if addFirst then "unshift" else "push"] subscriber
+    # Adds a responder for a stimulus, but the responder is added first in the list.
+    # Otherwise, the same as `respondTo()`.
+    # Returns this module's exports, for easy chaining of calls.
+    exports.respondFirst = exports.first = (stimulusName, responder) ->
+      addSub stimulusName, true, responder

-    return
+      return exports

-  # Adds a responder for a stimulus.  The stimulus name consists of a simple topic name
-  # (used when publishing a message), and optional set of namespaces; each namespace
-  # is preceded by a '.'.  The namespaces make it easier to identify specific responders
-  # later, such as when removing a responder.
-  # The ordering identifies where the listener will be placed.
-  # The listenerfn is a function to be invoked via the publisher. A topic publisher
-  # will publish a message with an application-specific memo.  The listenerfn receives
-  # the memo parameter, and an event parameter.  The event parameter allows the
-  # message to be terminated early.
-  # stimulus - name of stimulus to respond to, with namespaces appended
-  # responder - function to be invoked when the stimulus is fired. The responder
-  # is passed a memo object, and an event. The event can be used to cancel or
-  # pause the stimulus.
-  # Returns this module's exports, for easy chaining of calls.
-  exports.respondTo = exports.on = (stimulusName, responder) ->
+    # Stops responding to a stimulus. The parameters identify zero or more responders
+    # that will no longer be triggered.
+    # Only previously added responders that match a specifically as possible will be removed.
+    # If a responder is provided, it must match exactly.
+    # If a stimulus name is provided, the name must match exactly.
+    # If any namespaces were provided, then at least ONE namespace must match a namespace provided when
+    # the responder was added.
+    #
+    # * stimulusName - optional, identifies a stimulus and optional namespaces
+    # * responder - optional, identifies a specific responder to remove
+    #
+    # Returns this module's exports, to support chaining.
+    exports.stopResponding = exports.off = (stimulusName = "", responder) ->
+      if _.isFunction stimulusName
+        responder = stimulusName
+        stimulusName = ""

-    addSub stimulusName, false, responder
+      [simpleName, namespaces...] = stimulusName.split '.'

-    return exports
+      if simpleName isnt ""
+        kullSubs simpleName, namespaces, responder
+      else
+        kullSubs name, namespaces, responder for name of subscribers

-  # Adds a responder for a stimulus, but the responder is added first in the list.
-  # Otherwise, the same as respondsTo().
-  # Returns this module's exports, for easy chaining of calls.
-  exports.respondFirst = exports.first = (stimulusName, responder) ->
-    addSub stimulusName, true, responder
-
-    return exports
-
-  # Stops responding to a stimulus. The parameters identify zero or more responders
-  # that will no longer be triggered.
-  # Only previously added responders that match a specifically as possible will be removed.
-  # If a responder is provided, it must match exactly.
-  # If a stimulus name is provided, the name must match exactly.
-  # If any namespaces were provided, then at least ONE namespace must match a namespace provided when
-  # the responder was added.
-  # stimulusName - optional, identifies a stimulus and optional namespaces
-  # responder - optional, identifies a specific responder to remove
-  # Returns this module's exports, to support chaining.
-  exports.stopResponding = exports.off = (stimulusName = "", responder) ->
-    if _.isFunction stimulusName
-      responder = stimulusName
-      stimulusName = ""
-
-    [simpleName, namespaces...] = stimulusName.split '.'
-
-    if simpleName isnt ""
-      kullSubs simpleName, namespaces, responder
-    else
-      kullSubs name, namespaces, responder for name of subscribers
-
-    return exports
+      return exports

-  # Fires the stimulus, passing the memo and an event to each responder that was previously added.
-  # The event can be used to terminate the stimular prematurely, via its stop() method.
-  # The context object defines the value of this for
-  # the invoked responders; it is often null (or omitted).
-  # stimulusName - simple name of stimulus to fire (it should not contain namespaces)
-  # memo - object to be passed to each responder (as the first parameter)
-  # context - context value (this) used when invoking responders
-  # Returns this module's exports, to support chaining.
-  exports.fire = (stimulusName, memo, context) ->
-    list = subscribers[stimulusName]
+    # Fires the stimulus, passing the memo and an event to each responder that was previously added.
+    # The event can be used to terminate the stimular prematurely, via its stop() method.
+    # The context object defines the value of this for
+    # the invoked responders; it is often null (or omitted).
+    # stimulusName - simple name of stimulus to fire (it should not contain namespaces)
+    #
+    # * memo - object to be passed to each responder (as the first parameter)
+    # * context - context value (this) used when invoking responders
+    #
+    # Returns this module's exports, to support chaining.
+    exports.fire = (stimulusName, memo, context) ->
+      list = subscribers[stimulusName]

-    return exports if not list
+      return exports if not list

-    event =
-      memo: memo
-      running: true
-      stimulus: stimulusName
-      stop: -> running = false
-      # TODO: pause and resume
+      event =
+        memo: memo
+        running: true
+        stimulus: stimulusName
+        stop: -> running = false
+        # TODO: pause and resume

-    try
-      wasIterating = list.iterating
-      list.iterating = true
+      try
+        wasIterating = list.iterating
+        list.iterating = true

-      for subscriber in list when event.running
-        # Pass the memo and the event to the responder.
-        subscriber.fn.call context, memo, event
+        for subscriber in list when event.running
+          # Pass the memo and the event to the responder.
+          subscriber.fn.call context, memo, event

-    finally
-      list.iterating = wasIterating
+      finally
+        list.iterating = wasIterating

+      return exports
+
+    # Result of define:
     return exports
-
-  # Result of define:
-  return exports
-


PR #597: removed console.log

PR #597: removed console.log

--- test/integration/transactionsAPITests.coffee
+++ test/integration/transactionsAPITests.coffee
@@ -332,7 +332,6 @@
               validateEvents = ->
                 Event.find {}, (err, events) ->
                   return done err if err
-                  console.log events
                   events.length.should.be.exactly 6 #2+2+2 start/end for each of primary, async route and orchestration
                   eventRoutes = events.map (ev) -> ev.route
                   eventRoutes.should.containEql 'primary'


car_crashes: get the scatterplots in there

--- car_crashes/car_crashes.coffee
+++ car_crashes/car_crashes.coffee
@@ -5,24 +5,21 @@
     # sizes of things
     htop = 530
     hbot = 500
-    height = htop + hbot
+    height = htop + hbot+200

     margin_top = {left:5, top:20, right:25, bottom:40, inner:0}
     fullpanelwidth_top = 180
     panelwidth_top = fullpanelwidth_top - margin_top.left - margin_top.right
     panelheight_top = htop - margin_top.top - margin_top.bottom
-    statenamewidth = 201
+    statenamewidth = 101
     width = statenamewidth + fullpanelwidth_top*6

-    margin_bot = {left:60, top:40, right:40, bottom:40, inner:5}
+    margin_bot = {left:60, top:20, right:25, bottom:40, inner:5}

-    panelwidth_bot = width/3
-
-    # print the sizes of things
-    console.log("width = #{width}")
-    console.log("height = #{height}")
-    console.log("top width = #{panelwidth_top}")
-    console.log("bot width = #{panelwidth_bot}")
+    fullpanelwidth_bot = width/3
+    panelwidth_bot = fullpanelwidth_bot - margin_bot.left - margin_bot.right
+    fullpanelheight_bot = hbot/2
+    panelheight_bot = fullpanelheight_bot - margin_bot.top - margin_bot.bottom

     # make the svg
     svg = d3.select("div#chart")
@@ -34,10 +31,11 @@
     top_panel_var = ["total", "not_distracted", "speeding", "alcohol", "ins_premium", "ins_losses"]
     xlim = [[0,25],[0,25],[0,25],[0,25],[0,1500],[0,200]]
     nxticks = [6,6,6,6, 4, 5]
-    xlab = ["Crashes per billion miles", "Crashes per billion miles", "Crashes per billion miles", "Crashes per billion miles", "Dollars", "Dollars"]
+    xlab = ["Crashes per billion miles", "Crashes per billion miles", "Crashes per billion miles",
+            "Crashes per billion miles", "Dollars", "Dollars"]
     title = ["Total", "Not distracted", "Speeding", "Alcohol", "Ave. Ins. premium", "Ave. Ins. Losses"]

-    # now make the dot plots
+    # make the dot plots
     dotplots = []
     for i of top_panel_var

@@ -72,8 +70,6 @@
         points = this_dotplot.pointsSelect().on("mouseover.paneltip", (d) -> d)
                                             .on("mouseout.paneltip", (d) -> d)

-
-
         points.on("mouseover", highlight_state)
               .on("mouseout",  lowlight_state)

@@ -98,10 +94,60 @@
                      .on("mouseout",  lowlight_state)

+    # variables for lower scatterplots
+    row = [0, 0, 0, 1, 1, 1]
+    col = [0, 1, 2, 0, 1, 2]
+    lower_xvar = [0, 0, 0, 0, 0, 4]
+    lower_yvar = [1, 2, 3, 4, 5, 5]
+
+    # make the scatterplots
+    scatterplots = []
+    for i of top_panel_var
+
+        this_scatterplot = scatterplot().width(panelwidth_bot)
+                                    .height(panelheight_bot)
+                                    .margin(margin_bot)
+                                    .titlepos(10)
+                                    .xNA({handle:false})
+                                    .yNA({handle:false})
+                                    .xlim(xlim[lower_xvar[i]])
+                                    .ylim(xlim[lower_yvar[i]])
+                                    .nxticks(nxticks[lower_xvar[i]])
+                                    .nyticks(nxticks[lower_yvar[i]])
+                                    .xlab(xlab[lower_xvar[i]])
+                                    .ylab(xlab[lower_yvar[i]])
+                                    .pointsize(3)
+                                    .dataByInd(false)
+                                    .xvar(top_panel_var[lower_xvar[i]])
+                                    .yvar(top_panel_var[lower_yvar[i]])
+        scatterplots.push(this_scatterplot)
+
+        hpos = fullpanelwidth_bot*col[i]
+        vpos = htop+row[i]*fullpanelheight_bot+margin_bot.top
+        this_g = svg.append("g")
+                    .attr("class", "scatterplot")
+                    .attr("id", "scatterplot#{i}")
+                    .attr("transform", "translate(#{hpos},#{vpos})")
+
+        this_g.datum({data:data, indID:data.abbrev})
+              .call(this_scatterplot)
+
+        # remove the tool tips
+        d3.selectAll(".d3-tip").remove()
+        points = this_scatterplot.pointsSelect().on("mouseover.paneltip", (d) -> d)
+                                                .on("mouseout.paneltip", (d) -> d)
+
+        points.on("mouseover", highlight_state)
+              .on("mouseout",  lowlight_state)
+
+
+
+
 highlight_state = (d,i) ->
     d3.selectAll("circle.pt#{i}")
       .attr("fill", "Orchid")
       .attr("r", 5)
+      .moveToFront()
     d3.select("text#state#{i}")
       .attr("fill", "violetred")

@@ -109,6 +155,7 @@
     d3.selectAll("circle.pt#{i}")
       .attr("fill", "slateblue")
       .attr("r", 3)
+      .moveToBack()
     d3.select("text#state#{i}")
       .attr("fill", "black")


activity: reset panes to take a callback

--- client/activity/lib/components/privatemessagethreadpane/index.coffee
+++ client/activity/lib/components/privatemessagethreadpane/index.coffee
@@ -119,7 +119,7 @@

 React.Component.include.call PrivateMessageThreadPane, [KDReactorMixin]

-reset = (props, state) ->
+reset = (props, state, callback = kd.noop) ->

   { followedChannels, channelThread } = state
   { privateChannelId } = props.routeParams
@@ -137,6 +137,8 @@
     channelActions.loadChannel(privateChannelId).then ({ channel }) ->
       threadActions.changeSelectedThread channel.id
       channelActions.loadParticipants channel.id, channel.participantsPreview
+      callback()
   else if not channelThread
     threadActions.changeSelectedThread null
+    callback()


only update client filetree on success

only update client filetree on success

--- services/web/public/coffee/ide/file-tree/FileTreeManager.coffee
+++ services/web/public/coffee/ide/file-tree/FileTreeManager.coffee
@@ -341,12 +341,12 @@

 		renameEntity: (entity, name, callback = (error) ->) ->
 			return if entity.name == name
-			if name.length < 150
+			return if name.length >= 150
+			@ide.$http.post("/project/#{@ide.project_id}/#{entity.type}/#{entity.id}/rename", {
+				name: name,
+				_csrf: window.csrfToken
+			}).then () ->
 				entity.name = name
-			return @ide.$http.post "/project/#{@ide.project_id}/#{entity.type}/#{entity.id}/rename", {
-				name: entity.name,
-				_csrf: window.csrfToken
-			}

 		deleteEntity: (entity, callback = (error) ->) ->
 			# We'll wait for the socket.io notification to
@@ -362,11 +362,11 @@
 			# Abort move if the folder being moved (entity) has the parent_folder as child
 			# since that would break the tree structure.
 			return if @_isChildFolder(entity, parent_folder)
-			@_moveEntityInScope(entity, parent_folder)
-			return @ide.queuedHttp.post "/project/#{@ide.project_id}/#{entity.type}/#{entity.id}/move", {
+			@ide.queuedHttp.post("/project/#{@ide.project_id}/#{entity.type}/#{entity.id}/move", {
 				folder_id: parent_folder.id
 				_csrf: window.csrfToken
-			}
+			}).then () =>
+				@_moveEntityInScope(entity, parent_folder)

 		_isChildFolder: (parent_folder, child_folder) ->
 			parent_path = @getEntityPath(parent_folder) or "" # null if root folder


Workspace: Connectivity issue notification is mini now.

--- client/landing/CollaborativeWorkspace/collaborativeworkspace.coffee
+++ client/landing/CollaborativeWorkspace/collaborativeworkspace.coffee
@@ -415,6 +415,8 @@
       title       : message
       duration    : 20000
       container   : this
+      cssClass    : "error"
+      type        : "mini"
       overlay     : {}

   hideNotification: ->


JS: remove unused import and fix intendation in oxivalue-format/types

--- core/htdocs_source/app/pods/components/oxivalue-format/types.coffee
+++ core/htdocs_source/app/pods/components/oxivalue-format/types.coffee
@@ -1,27 +1,26 @@
-import Em from "components-ember"
 import moment from "moment"

 types =
-        certstatus: (v) -> "#{v.label}"
-        link: (v) -> "#{v.label}"
-        extlink: (v) -> "#{v.label}"
-        timestamp: (v) ->
-          if v > 0
+    certstatus: (v) -> "#{v.label}"
+    link: (v) -> "#{v.label}"
+    extlink: (v) -> "#{v.label}"
+    timestamp: (v) ->
+        if v > 0
             moment.unix(v).utc().format("YYYY-MM-DD HH:mm:ss UTC")
-          else
+        else
             "---"
-        datetime: (v) -> moment().utc(v).format("YYYY-MM-DD HH:mm:ss UTC")
-        text: (v) -> Em.$('
').text(v).html()
-        nl2br: (v) -> Em.$('
').text(v).html().replace(/\n/gm,"
")
-        code: (v) -> "#{ Em.$('
').text(v).html().replace(/\r/gm,"")}"
-        raw: (v) -> v
-        defhash: (v) -> "
#{(for k, w of v then "
#{k}

#{ Em.$('
').text(w).html() }
").join ""}
"
-        deflist: (v) -> "
#{(for w in v then "
#{w.label}

#{(if w.format is "raw" then w.value else Em.$('
').text(w.value).html())}
").join ""}
"
-        ullist: (v) -> "
#{(for w in v then "
#{Em.$('
').text(w).html()}
").join ""}
"
-        rawlist: (v) -> "
#{(for w in v then "
#{w}
").join ""}
"
-        linklist: (v) -> "
#{(for w in v then "
#{w.label}
").join ""}
"
-        styled: (v) -> Em.$('').text(v).html().replace(/(([a-z]+):)?(.*)/gm, '$3')
-        tooltip: (v) -> "#{v.value}"
-        head: (v) -> "1";
+    datetime: (v) -> moment().utc(v).format("YYYY-MM-DD HH:mm:ss UTC")
+    text: (v) -> Em.$('
').text(v).html()
+    nl2br: (v) -> Em.$('
').text(v).html().replace(/\n/gm,"
")
+    code: (v) -> "#{ Em.$('
').text(v).html().replace(/\r/gm,"")}"
+    raw: (v) -> v
+    defhash: (v) -> "
#{(for k, w of v then "
#{k}

#{ Em.$('
').text(w).html() }
").join ""}
"
+    deflist: (v) -> "
#{(for w in v then "
#{w.label}

#{(if w.format is "raw" then w.value else Em.$('
').text(w.value).html())}
").join ""}
"
+    ullist: (v) -> "
#{(for w in v then "
#{Em.$('
').text(w).html()}
").join ""}
"
+    rawlist: (v) -> "
#{(for w in v then "
#{w}
").join ""}
"
+    linklist: (v) -> "
#{(for w in v then "
#{w.label}
").join ""}
"
+    styled: (v) -> Em.$('').text(v).html().replace(/(([a-z]+):)?(.*)/gm, '$3')
+    tooltip: (v) -> "#{v.value}"
+    head: (v) -> "1"

 export default types


Turbolinks 5 fixes

Turbolinks 5 fixes

--- app/assets/javascripts/effective_datatables/initialize.js.coffee
+++ app/assets/javascripts/effective_datatables/initialize.js.coffee
@@ -185,16 +185,10 @@
     if $.fn.DataTable.fnIsDataTable(this)
       $(this).DataTable().destroy()

-anotherDestroy = ->
-  for settings in $.fn.dataTable.settings
-    $(settings.nTableWrapper).unbind('.DT').find(':not(tbody *)').unbind('.DT')
-    $(window).unbind('.DT-'+settings.sInstance)
-
-  $.fn.dataTable.settings.length = 0
-
 $ -> initializeDataTables()
 $(document).on 'page:change', -> initializeDataTables()
 $(document).on 'turbolinks:load', -> initializeDataTables()
+$(document).on 'turbolinks:render', -> initializeDataTables()
 $(document).on 'turbolinks:before-cache', -> destroyDataTables()


When setting the current feed or folder in the angularjs app, hide the sidebar instead of toggling its current visibility state.

When the only way to set the feed/folder was clicking on the sidebar links, toggling worked fine because for this to happen the sidebar had to be visible, and toggling made it hidden. However now the current feed can also be set by clicking on the feed link in a job status alert; when this happens the sidebar is hidden, and toggling it would make it shown, which is the opposite of the desired behavior. The fix is to hide it unconditionally.

The fix is only really necessary when setting the current feed, but it's also applied when setting the current folder for coherence in the code.

--- app/assets/javascripts/ng-controllers/ng-FeedbunchCtrl.js.coffee
+++ app/assets/javascripts/ng-controllers/ng-FeedbunchCtrl.js.coffee
@@ -134,7 +134,7 @@
       feedsFoldersSvc.load_feed feed_id
       menuCollapseSvc.close()
       $timeout ->
-        sidebarVisibleSvc.toggle()
+        sidebarVisibleSvc.set false
       , 300
     return

@@ -146,7 +146,7 @@
     readSvc.read_entries_page()
     menuCollapseSvc.close()
     $timeout ->
-      sidebarVisibleSvc.toggle()
+      sidebarVisibleSvc.set false
     , 300
     return


OX-561 fixed typo

OX-561 fixed typo

--- app/assets/javascripts/oxalis/controller/plane_controller.coffee
+++ app/assets/javascripts/oxalis/controller/plane_controller.coffee
@@ -349,7 +349,7 @@
     # Strg + Rightclick to set new not active branchpoint
     if ctrlPressed and
       @model.user.newNodeNewTree == false and
-        @model.route.getActiveNodeType == constants.TYPE_USUAL
+        @model.route.getActiveNodeType() == constants.TYPE_USUAL

       @pushBranch()
       @setActiveNode(activeNode.id)


Added guard to ProductsCtrl.loadNextPage() when loadingComplete or fetching

--- app/assets/javascripts/sprangular/controllers/productList.coffee
+++ app/assets/javascripts/sprangular/controllers/productList.coffee
@@ -15,6 +15,8 @@
   $scope.selectedVariants = {}

   $scope.loadNextPage = ->
+    return if $scope.loadingComplete || $scope.fetching
+
     $scope.fetching = true

     load = if taxon


minor fix for band

minor fix for band

--- app/views/settings/spacewarp_viewer.coffee
+++ app/views/settings/spacewarp_viewer.coffee
@@ -18,15 +18,16 @@
     @model.tool.on 'swviewer:loaded', =>

       opts = @model.tool.opts
+
+      if opts.stretch?
+        @$el.find("##{opts.stretch}-#{@cid}").click()
+      else
+        @$el.find("#linear-#{@cid}").click()
+
       if opts.band?
         @$el.find("##{opts.band}-#{@cid}").click()
       else
         @$el.find("#gri-#{@cid}").click()
-
-      if opts.stretch?
-        @$el.find("##{opts.stretch}-#{@cid}").click()
-      else
-        @$el.find("#linear-#{@cid}").click()

       # Update UI elements
       inputs = @$el.find('input[type="range"]')


Providers: Softlayer: update tests for the new provider implementation

--- workers/social/lib/social/models/computeproviders/softlayer.test.coffee
+++ workers/social/lib/social/models/computeproviders/softlayer.test.coffee
@@ -14,7 +14,6 @@

 JMachine     = require './machine'
 Softlayer    = require './softlayer'
-JDomainAlias = require '../domainalias'

 # this function will be called once before running any test
@@ -67,96 +66,9 @@
           expect(err).to.not.exist
           expect(data.meta).to.be.an 'object'
           expect(data.meta.type).to.be.equal 'softlayer'
-          expect(data.meta.storage_size).to.be.equal 25
-          expect(data.meta.alwaysOn).to.be.false
-          expect(data.label).to.be.a 'string'
-          expect(data.credential).to.be.equal user.username
+          expect(data.meta.storage_size).to.be.equal 10
+          expect(data.meta.assignedLabel).to.be.equal options.label
           done()
-
-
-  describe '#postCreate()', ->
-
-    it 'should create domain alias and workspace', (done) ->
-
-      withConvertedUser ({ userFormData, client, account }) ->
-
-        client.r  = { account }
-        machine   = {}
-
-        queue = [
-
-          (next) ->
-            fetchMachinesByUsername userFormData.username, (machines) ->
-              machine = machines[0]
-              next()
-
-          (next) ->
-            Softlayer.postCreate client, { machine }, (err, workspace_) ->
-              expect(err).to.not.exist
-              expect(workspace_.isDefault).to.be.truthy
-              expect(workspace_.machineUId).to.be.equal machine.uid
-              expect(workspace_.originId).to.be.deep.equal account._id
-              next()
-
-          (next) ->
-            options   = { machineId : machine._id.toString() }
-            topDomain = "#{account.profile.nickname}.#{KONFIG.userSitesDomain}"
-            JDomainAlias.one options, (err, domainAlias) ->
-              expect(domainAlias.domain).to.be.equal topDomain
-              expect(domainAlias.originId).to.be.deep.equal account._id
-              next()
-
-        ]
-
-        async.series queue, done
-
-
-
-  describe '#update()', ->
-
-    it 'should fail if required options is not set', (done) ->
-
-      withConvertedUser ({ client, account, user, userFormData }) ->
-
-        client.r      = { account, user }
-        expectedError = 'A valid machineId and an update option required.'
-        Softlayer.update client, {}, (err) ->
-          expect(err?.message).to.be.equal expectedError
-          done()
-
-
-    it 'should be able to succeed with valid request', (done) ->
-
-      withConvertedUser ({ client, account, group, user, userFormData }) ->
-
-        machine  = {}
-        client.r = { account, user, group }
-
-        queue = [
-
-          (next) ->
-            fetchMachinesByUsername userFormData.username, (machines) ->
-              machine = machines[0]
-              next()
-
-          (next) ->
-            options =
-              alwaysOn  : false
-              machineId : machine._id.toString()
-
-            Softlayer.update client, options, (err) ->
-              expect(err?.message).to.not.exist
-              next()
-
-          (next) ->
-            JMachine.one { _id : machine._id }, (err, machine_) ->
-              expect(err?.message).to.not.exist
-              expect(machine_.alwaysOn).to.be.falsy
-              next()
-
-        ]
-
-        async.series queue, done

 beforeTests()


breakpoint keybinding on windows

breakpoint keybinding on windows

--- keymaps/julia-client.cson
+++ keymaps/julia-client.cson
@@ -42,6 +42,7 @@
   'ctrl-j ctrl-m': 'julia-client:set-working-module'
   'ctrl-shift-c': 'julia-client:interrupt-julia'
   'ctrl-j ctrl-d': 'julia-client:toggle-documentation'
+  'alt-x': 'julia-debug:toggle-breakpoint'

 '.platform-win32 ink-console.julia,
  .platform-win32 ink-console.julia atom-text-editor,


Remove deprecated shadowRoot property reference

--- spec/bookmarks-view-spec.coffee
+++ spec/bookmarks-view-spec.coffee
@@ -9,11 +9,7 @@
       .map (decoration) -> decoration.screenRange

   getBookmarkedLineNodes = (editorElement) ->
-    # TODO: Remove this after light DOM for editors ships on stable.
-    if editorElement.lightDOM
-      editorElement.querySelectorAll('.bookmarked')
-    else
-      editorElement.shadowRoot.querySelectorAll('.bookmarked')
+    editorElement.querySelectorAll('.bookmarked')

   beforeEach ->
     spyOn(window, 'setImmediate').andCallFake (fn) -> fn()