Minor clarification to comments.

Minor clarification to comments.

--- keypress.coffee
+++ keypress.coffee
@@ -33,7 +33,7 @@
     on_keydown      : null          - A function that is called when the combo is pressed.
     on_keyup        : null          - A function that is called when the combo is released.
     on_release      : null          - A function that is called when all keys in the combo are released.
-    this            : undefined     - The scope for 'this' of your callback functions.
+    this            : undefined     - Defines the scope for your callback functions.
 ###

 ###########


Combo class should not be public.

Combo class should not be public.

--- keypress.coffee
+++ keypress.coffee
@@ -60,7 +60,7 @@

 keypress.debug = false

-class keypress.Combo
+class Combo
     constructor: (dictionary) ->
         # Copy over any non-false values
         for own property, value of dictionary
@@ -532,7 +532,7 @@
         for own property, value of @_defaults
             if combo_dictionary[property] == undefined
                 combo_dictionary[property] = value
-        combo = new keypress.Combo combo_dictionary
+        combo = new Combo combo_dictionary

         if _validate_combo combo
             @_registered_combos.push combo


Some bug fixes in log.coffee

Some bug fixes in log.coffee

--- src/log.coffee
+++ src/log.coffee
@@ -16,12 +16,13 @@
 	exports.level 'info', out...

 for name of levels
-	exports[name[0]] = exports[name] =
-		(out...) ->
-			exports.level name, out...
+	do (name) ->
+		exports[name[0]] = exports[name] =
+			(out...) ->
+				exports.level name, out...

 exports.level = (level, out...) ->
-	if levels[level ? 'error'] <= levels[logLevel]
+	if levels[level ? 'error'] >= levels[logLevel]
 		logImpl.log level, out...

 exports.initialize = initialize


Tabs to spaces

Tabs to spaces

--- test/files/stream.iced
+++ test/files/stream.iced
@@ -7,82 +7,82 @@
 #==========================================================

 loop_limit = 5000
-loop_skip = 27
+loop_skip = 29

 stream_random_data = (strm, len) ->
-	data = prng(len)
-	i = 0
-	j = 0
-	while i < data.length
-		j = i + prng(1)[0]
-		strm.write(data[i...j])
-		i = j
-	data
+  data = prng(len)
+  i = 0
+  j = 0
+  while i < data.length
+    j = i + prng(1)[0]
+    strm.write(data[i...j])
+    i = j
+  data

 test_bx_consistency = (T, base, len) ->
-	encoding = encoding_for_base(base)
-	encoder = new stream.StreamEncoder(encoding)
-	decoder = new stream.StreamDecoder(encoding)
+  encoding = encoding_for_base(base)
+  encoder = new stream.StreamEncoder(encoding)
+  decoder = new stream.StreamDecoder(encoding)

-	encoder.pipe(decoder)
+  encoder.pipe(decoder)

-	data = stream_random_data(encoder, len)
-	decoded_data = decoder.read()
-	leftovers = encoder.read(0)
+  data = stream_random_data(encoder, len)
+  decoded_data = decoder.read()
+  leftovers = encoder.read(0)

-	T.equal(data, decoded_data, "inconsistency found: base=#{base} len=#{len} leftovers=#{leftovers}")
+  T.equal(data, decoded_data, "inconsistency found: base=#{base} len=#{len} leftovers=#{leftovers}")

 test_bx_output = (T, base, len, stock_func) ->
-	encoding = encoding_for_base(base)
-	encoder = new stream.StreamEncoder(encoding)
-	data = prng(len)
-	stock = stock_func(data)
+  encoding = encoding_for_base(base)
+  encoder = new stream.StreamEncoder(encoding)
+  data = prng(len)
+  stock = stock_func(data)

-	encoder.write(data)
-	encoded_data = encoder.read().toString()
-	leftovers = encoder.read(0)
+  encoder.write(data)
+  encoded_data = encoder.read().toString()
+  leftovers = encoder.read(0)

-	T.equal(stock, encoded_data, "bad output found: base=#{base} len=#{len} leftovers=#{leftovers}")
+  T.equal(stock, encoded_data, "bad output found: base=#{base} len=#{len} leftovers=#{leftovers}")

 encoding_for_base = (base) ->
-	switch base
-		when 58 then enc.b58.encoding
-		when 62 then enc.b62.encoding
-		when 64 then enc.b64.encoding
+  switch base
+    when 58 then enc.b58.encoding
+    when 62 then enc.b62.encoding
+    when 64 then enc.b64.encoding

 b64stock =
-	encode : (x) ->
-		r = new RegExp('=', 'g')
-		x.toString('base64').replace(r, '')
-	decode : (x) ->
-		until (x.length % 4) is 0
-			x += "="
-		return new Buffer x, 'base64'
+  encode : (x) ->
+    r = new RegExp('=', 'g')
+    x.toString('base64').replace(r, '')
+  decode : (x) ->
+    until (x.length % 4) is 0
+      x += "="
+    return new Buffer x, 'base64'

 #==========================================================
 #These tests encode then immediately decode, and compare the result to the original text
 #=========================================================

 exports.test_b58_consistency = (T, cb) ->
-	for i in [1...loop_limit] by loop_skip
-		test_bx_consistency(T, 58, i)
-	cb()
+  for i in [1...loop_limit] by loop_skip
+    test_bx_consistency(T, 58, i)
+  cb()

 exports.test_b62_consistency = (T, cb) ->
-	for i in [1...loop_limit] by loop_skip
-		test_bx_consistency(T, 62, i)
-	cb()
+  for i in [1...loop_limit] by loop_skip
+    test_bx_consistency(T, 62, i)
+  cb()

 exports.test_b64_consistency = (T, cb) ->
-	for i in [1...loop_limit] by loop_skip
-		test_bx_consistency(T, 64, i)
-	cb()
+  for i in [1...loop_limit] by loop_skip
+    test_bx_consistency(T, 64, i)
+  cb()

 #=========================================================
 #These tests check whether or not the encoding is valid
 #=========================================================

 exports.test_b64_output = (T, cb) ->
-	for i in [1...loop_limit] by loop_skip
-		test_bx_output(T, 64, i, b64stock.encode)
-	cb()
+  for i in [1...loop_limit] by loop_skip
+    test_bx_output(T, 64, i, b64stock.encode)
+  cb()


test: Add test for git clone.

test: Add test for git clone.

--- test/index.spec.coffee
+++ test/index.spec.coffee
@@ -1,5 +1,7 @@
 expect = require('chai').expect
 fs = require 'fs-extended'
+cp = require 'child_process'
+{spawn, exec} = require 'child_process'

 Inotifyr = require '../'

@@ -29,3 +31,22 @@
       done()

     fs.createDirSync './test/fixtures/new'
+
+
+  it 'should register all add events for a git clone', (done) ->
+      @timeout 5000
+      watcher = new Inotifyr 'test/fixtures'
+      count = 0
+      watcher.on 'add', (filename, stats) ->
+        count++
+
+      git = spawn 'git', ['clone', 'https://github.com/codio/node-demo.git', 'test/fixtures/node-demo']
+      git.stdout.on 'data', (data) -> console.log data.toString()
+      git.stderr.on 'data', (data) -> console.log data.toString()
+      git.on 'close', (code) ->
+        expect(code).to.be.eql 0
+
+        exec 'find test/fixtures/node-demo -type f -print | wc -l', (err, stdout, stderr) ->
+          expect(count).to.be.eql parseInt(stdout, 10)
+          done()
+


Updated test file spacing

Updated test file spacing

--- test/index_spec.coffee
+++ test/index_spec.coffee
@@ -1,11 +1,13 @@
 should = require('chai').should()
 Promise = require('promise')
+
 ChuckApi = require('../src/index.coffee')

 before ->
   @chuck = new ChuckApi()

 describe 'Chuck Api Reader', ->
+
   describe 'all', ->
     it 'should return the correct number of jokes', ->
       @chuck.getAllJokes().then (jokes) ->
@@ -55,6 +57,7 @@
           joke.categories.should.not.contain 'explicit',
             'Returning jokes with excluded category'

+
   describe 'categories', ->
     it 'should get all categories', ->
       @chuck.getCategories().then (categories) ->
@@ -62,11 +65,13 @@
         categories.value.should.deep.equal ['explicit', 'nerdy'],
           'Unexpected categories present'

+
   describe 'count', ->
     it 'should return the number of jokes', ->
       @chuck.getCount().then (count) ->
         count.type.should.equal 'success', 'Joke count request unsuccesful'
         count.value.should.be.above 500, 'Unexpected joke count recieved'
+

   describe 'random', ->
     it 'should return a random joke', ->
@@ -127,6 +132,7 @@
             joke.categories.should.not.contain 'explicit',
               'Returning random joke with excluded category'

+
   describe 'specific', ->
     it 'should return a specific joke by Id', ->
       @chuck.getJoke(469).then (joke) ->


added test items

added test items

--- test/js/totodoo.coffee
+++ test/js/totodoo.coffee
@@ -19,7 +19,24 @@
 	beforeEach ->
 		@driver.get 'http://127.0.0.1/'

-	it 'has the title of the application in the window\'s title', (done) ->
-		expect(@driver.getTitle()).to.eventually.contain
-		'Totodoo App'
-		@timeout 4000, done()
+	describe 'Init', ->
+
+		it 'has the title of the application in the window\'s title', (done) ->
+			expect(@driver.getTitle()).to.eventually.contain
+			'Totodoo App'
+			@timeout 4000, done()
+
+	describe 'Lists', ->
+
+		describe 'Select list', ->
+
+		describe 'Create list', ->
+
+		describe 'Modify list', ->
+
+		describe 'Delete list', ->
+
+	describe 'Items', ->
+
+	describe 'User', ->
+


Bugfix: add missing radius for initial geolocate.

--- src/map.coffee
+++ src/map.coffee
@@ -114,6 +114,7 @@
                 return
             lat_lng = L.latLng [pos.coords.latitude, pos.coords.longitude]
             accuracy = pos.coords.accuracy
+            radius = 4
             if not @user_position_markers?
                 opts =
                     weight: 0
@@ -121,7 +122,7 @@
                 @map.addLayer accuracy_marker
                 opts =
                     color: '#ff0000'
-                    radius: 4
+                    radius: radius
                 marker = L.circleMarker lat_lng, opts
                 @map.addLayer marker
                 @user_position_markers =


Remove code that was only executed on jankies

--- build/tasks/spec-task.coffee
+++ build/tasks/spec-task.coffee
@@ -3,20 +3,6 @@

 module.exports = (grunt) ->
   {spawn} = require('./task-helpers')(grunt)
-
-  logDeprecations = (label, {stderr}={}) ->
-     return unless process.env.JANKY_SHA1
-     stderr ?= ''
-     deprecatedStart = stderr.indexOf('Calls to deprecated functions')
-     return if deprecatedStart is -1
-
-     grunt.log.error(label)
-     stderr = stderr.substring(deprecatedStart)
-     stderr = stderr.replace(/^\s*\[[^\]]+\]\s+/gm, '')
-     stderr = stderr.replace(/source: .*$/gm, '')
-     stderr = stderr.replace(/^"/gm, '')
-     stderr = stderr.replace(/",\s*$/gm, '')
-     grunt.log.error(stderr)

   getAppPath = ->
     pkgName = grunt.config.get 'name'
@@ -48,9 +34,6 @@
       if process.platform is 'win32'
         process.stderr.write(fs.readFileSync('ci.log')) if error
         fs.unlinkSync('ci.log')
-      else
-        # TODO: Restore concurrency on Windows
-        logDeprecations('Core Specs', results)

       callback(null, error)


closes #33

closes #33

--- src/coffee/controllers/login-ctrl.coffee
+++ src/coffee/controllers/login-ctrl.coffee
@@ -14,7 +14,7 @@
       $scope.nameToIdentifier = (name) -> "web-fe##{name}"

       goToPlayerView = ->
-        $state.go 'player'
+        $state.go 'player.overview'

       $scope.doLogin = ->
         data = _.clone $scope.login


Every homework that has been started and is past due shows a score, and every progress pie that is past due is blue.

--- src/components/scores/homework-cell.cjsx
+++ src/components/scores/homework-cell.cjsx
@@ -39,7 +39,7 @@
     scoreNumber = TH.getHumanScoreNumber(task)
     completed = task.completed_exercise_count is task.exercise_count
     scoreText = '---'
-    if completed
+    if completed or TH.isDue(task)
       if displayAs is 'number'
         scoreText = scoreNumber
       else
@@ -71,7 +71,7 @@
               isConceptCoach={isConceptCoach}
               size={20}
               value={TH.getCompletedPercent(task)}
-              isLate={TH.isLate(task)}
+              isLate={TH.isDue(task)}
             />
           </span>
         </BS.OverlayTrigger>


:art: cleanup

:art: cleanup

--- lib/move-selected-text.coffee
+++ lib/move-selected-text.coffee
@@ -11,14 +11,10 @@
 {pointIsAtEndOfLine, getVimLastBufferRow} = requireFrom('vim-mode-plus', 'utils')
 swrap = requireFrom('vim-mode-plus', 'selection-wrapper')

-CommandPrefix = 'vim-mode-plus-user'
-
 newState = ->
-  {
-    selectedTexts: null
-    checkpoint: null
-    overwritten: null
-  }
+  selectedTexts: null
+  checkpoint: null
+  overwritten: null

 stateByEditor = new Map
 disposableByEditor = new Map
@@ -26,6 +22,7 @@
 # -------------------------
 class MoveSelectedText extends TransformString
   @commandScope: 'atom-text-editor.vim-mode-plus.visual-mode'
+  @commandPrefix: 'vim-mode-plus-user'

   initialize: ->
     stateByEditor.set(@editor, newState()) unless stateByEditor.has(@editor)
@@ -63,7 +60,7 @@
     selections = @editor.getSelections()
     if @isLinewise()
       selections.map (selection) ->
-        _.multiplyString("\n", swrap(selection).getRowCount()-1)
+        swrap(selection).getRows().map(-> '').join("\n")
     else
       selections.map (selection) ->
         _.multiplyString(' ', selection.getBufferRange().getExtent().column)
@@ -117,7 +114,6 @@
           not swrap(selection).isSingleRow()

 class MoveSelectedTextUp extends MoveSelectedText
-  @commandPrefix: CommandPrefix
   direction: 'up'
   flashTarget: false

@@ -181,7 +177,7 @@
       when 'up' then [[-1, 0], [0, 0]]
       when 'down' then [[0, 0], [1, 0]]

-    swrap(selection).translate(translation)
+    swrap(selection).translate(translation...)

     lineTexts = swrap(selection).lineTextForBufferRows()
     @rotateRows(lineTexts)
@@ -210,7 +206,6 @@

 # -------------------------
 class MoveSelectedTextRight extends MoveSelectedText
-  @commandPrefix: CommandPrefix
   direction: 'right'
   flashTarget: false

@@ -246,7 +241,7 @@
       when 'right' then [[0, 0], [0, +1]]
       when 'left' then [[0, -1], [0, 0]]

-    swrap(selection).translate(translation)
+    swrap(selection).translate(translation...)
     newText = @rotate(selection.getText())
     range = selection.insertText(newText)
     range = range.translate(translation.reverse()...)


Remove empty spaces

Remove empty spaces

--- test/sshfs-test.coffee
+++ test/sshfs-test.coffee
@@ -42,7 +42,7 @@
   .addBatch
     'when mounting a server':
       topic: ->
-        options =
+        options =
           user: config.user
           port: config.port
         sshfs.mount config.host, mountPoint, options, this.callback
@@ -83,7 +83,7 @@
     'when mounting a server without callback':
       topic: ->
         callback = this.callback
-        options =
+        options =
           user: config.user
           port: config.port
         sshfs.mount config.host, mountPoint, options
@@ -108,4 +108,3 @@
       'we got no error': (err, arg2) ->
         assert.isNull err
   .export(module)
-


Workspace: Minor refactor for dry.

Workspace: Minor refactor for dry.

--- client/app/CommonViews/workspace/collaborativeworkspace.coffee
+++ client/app/CommonViews/workspace/collaborativeworkspace.coffee
@@ -38,15 +38,13 @@
       if isOldSession
         @sessionData  = keys
         @createPanel()
-        @userRef = @workspaceRef.child("users").child @nickname
-        @userRef.set "online"
-        @userRef.onDisconnect().set "offline"
       else
         @createPanel()
         @workspaceRef.set "keys": @sessionData
-        @userRef = @workspaceRef.child("users").child @nickname
-        @userRef.set "online"
-        @userRef.onDisconnect().set "offline"
+
+      @userRef = @workspaceRef.child("users").child @nickname
+      @userRef.set "online"
+      @userRef.onDisconnect().set "offline"

       if @amIHost()
         @workspaceRef.onDisconnect().remove()


add small same square detection

add small same square detection

--- src/puzzle.coffee
+++ src/puzzle.coffee
@@ -131,6 +131,8 @@
         return @

     swap: (p1, p2) ->
+        if p1 == p2
+            return @
         [y1, x1] = toPos.call(@, p1)
         [y2, x2] = toPos.call(@, p2)
         if x1 == x2 and y1 == y2


profile: refactored the giant constructor of many things into many methods of lesser things

--- client/landing/app/MainApp/lazy/staticprofilecontroller.coffee
+++ client/landing/app/MainApp/lazy/staticprofilecontroller.coffee
@@ -26,10 +26,105 @@
         cssClass        : 'static-content activity-related'
       showHeader        : no

+    # this is the JAccount object of the static profile
+    @profileUser  = null
+
     @navLinks     = {}
+    @lockSidebar  = no

     @registerSingleton 'staticProfileController', @, no

+    @reviveViewsOnPageLoad()
+    @addEventListeners()
+
+    # KD.remote.cacheable KD.config.profileEntryPoint, (err, user, name)=>
+    # FIXME - we want to use cacheable, not a JAccount call
+    KD.remote.api.JAccount.one
+      "profile.nickname" : KD.config.profileEntryPoint
+    , (err, user, name)=>
+      if err then log err,user,name
+      unless err
+        @reviveViewsOnUserLoad user
+
+  addEventListeners:->
+
+    @on 'HomeLinkClicked', =>
+      @lockSidebar = no
+      @utils.wait 250, =>
+        @profileContentLinks.setClass 'links-hidden'
+        @profileContentList.unsetClass 'has-links'
+
+      # HERE is the place to implement custom profile splash screens, reveal.js and such
+
+      @emit 'StaticProfileNavLinkClicked', 'CBlogPostActivity', yes
+
+    @on 'ActivityLinkClicked', (path)=>
+      @lockSidebar = yes
+      @emit 'StaticProfileNavLinkClicked', 'CBlogPostActivity'
+      @utils.wait 250, =>
+        @profileContentList.setClass 'has-links'
+        @profileContentLinks.unsetClass 'links-hidden'
+
+    @on 'CustomizeLinkClicked',=>
+      return if @customizeViewsAttached or KD.whoami().getId() isnt @profileUser.getId()
+      @customizeViewsAttached = yes
+
+      @avatarAreaIconMenu.emit 'CustomizeLinkClicked'
+
+      # reviving customization
+
+      types = @getAllowedTypes @profileUser
+
+      for type in CONTENT_TYPES
+        @navLinks[type].addSubView new StaticNavCheckBox
+          activityType : type
+          defaultValue : type in types
+          delegate     : @
+        , @profileUser
+
+    @on 'ShowMoreButtonClicked', =>
+      @emit 'StaticProfileNavLinkClicked', 'CBlogPostActivity'
+
+    @on 'StaticProfileNavLinkClicked', (facets,isStatic=no)=>
+      @profileLoadingBar.setClass 'active'
+      @profileLoaderView.show()
+      facets = [facets] if 'string' is typeof facets
+
+      if @profileUser
+        allowedTypes = @getAllowedTypes @profileUser
+
+        blockedTypes = facets.reduce (acc, facet)->
+          acc.push facet unless facet in allowedTypes
+          return acc
+        , []
+
+        @emit 'DecorateStaticNavLinks', allowedTypes
+
+        if blockedTypes.length is 0
+          @currentFacets = facets
+          appManager.tell 'Activity', 'fetchActivity',
+            originId : @profileUser.getId()
+            facets : facets
+            bypass : yes
+          , (err, activities)=>
+            @refreshActivities err, activities, isStatic
+        else @emit 'BlockedTypesRequested', blockedTypes
+
+    @controller.on 'LazyLoadThresholdReached', =>
+      appManager.tell 'Activity', 'fetchActivity',
+        originId  : @profileUser.getId()
+        facets    : @currentFacets
+        to        : @controller.itemsOrdered.last.getData().meta.createdAt
+        bypass    : yes
+      , @bound "appendActivities"
+
+  reviveViewsOnPageLoad:->
+
+    console.time 'reviving page elements on pageload.'
+
+    allowedTypes  = ['CBlogPostActivity']
+    blockedTypes  = []
+    @currentFacets = []
     # reviving the content view. this encapsulates the listitem feed after
     # user input (type selection, more-button)
     @profileContentView = new KDListView
@@ -44,12 +139,6 @@
     @profileContentView.addSubView @listWrapper
     @profileContentView.addSubView @staticListWrapper

-    # this is the JAccount object of the static profile
-    profileUser   = null
-    allowedTypes  = ['CBlogPostActivity']
-    blockedTypes  = []
-    currentFacets = []
-
     # reviving the landing page. this is needed to handle window
     # resize events for the view and subviews
     @profileLandingView = new KDView
@@ -58,10 +147,10 @@
     @profileLandingView.listenWindowResize()
     @profileLandingView._windowDidResize = =>
       @profileLandingView.setHeight window.innerHeight
-      @profileContentView.setHeight window.innerHeight-profileTitleView.getHeight()
+      @profileContentView.setHeight window.innerHeight-@profileTitleView.getHeight()
       @repositionLogoView()

-    profileTitleView = new KDView
+    @profileTitleView = new KDView
       lazyDomId : 'profile-title'

     @profileShowMoreView = new KDView
@@ -82,60 +171,35 @@

     # reviving wrapper views for resize/slide animations as well as
     # adding administrative views
-    profileContentWrapperView = new KDView
+    @profileContentWrapperView = new KDView
       lazyDomId : 'profile-content-wrapper'
       cssClass  : 'slideable'

-    profilePersonalWrapperView = new KDView
+    @profilePersonalWrapperView = new KDView
       lazyDomId : 'profile-personal-wrapper'
       cssClass  : 'slideable'
       bind : 'mouseenter mouseleave'
-
-    @lockSidebar = no
-
-    @on 'SidebarLockRequested', (state = yes)=>
-      @lockSidebar = state
-
-    @on 'HomeLinkClicked', =>
-      # @listWrapper.hide()
-      # @staticListWrapper.show()
-      @lockSidebar = no
-      profileContentLinks.setClass 'links-hidden'
-      profileContentList.unsetClass 'has-links'
-
-      # HERE is the place to implement custom profile splash screens, reveal.js and such
-      @emit 'StaticProfileNavLinkClicked', 'CBlogPostActivity', yes
-
-    @on 'ActivityLinkClicked', (path)=>
-      # @staticListWrapper.hide()
-      # @listWrapper.show()
-      @lockSidebar = yes
-      profileContentList.setClass 'has-links'
-      profileContentLinks.unsetClass 'links-hidden'
-      @emit 'StaticProfileNavLinkClicked', 'CBlogPostActivity'
-

     #
     # allow for sidebar lock here!
     # resize avatar to center or something
     #

-    profilePersonalWrapperView.on 'mouseenter',(event)=>
-        profilePersonalWrapperView.setWidth 160
-        profileContentWrapperView.$().css marginLeft : "160px"
-
-    profilePersonalWrapperView.on 'mouseleave',(event)=>
-      log @lockSidebar
+    @profilePersonalWrapperView.on 'mouseenter',(event)=>
+        @profilePersonalWrapperView.setWidth 160
+        @profileContentWrapperView.$().css marginLeft : "160px"
+
+    @profilePersonalWrapperView.on 'mouseleave',(event)=>
       unless @lockSidebar
-        profilePersonalWrapperView.setWidth 50
-        profileContentWrapperView.$().css marginLeft : "50px"
+        @profilePersonalWrapperView.setWidth 50
+        @profileContentWrapperView.$().css marginLeft : "50px"

     # reviving feed type selectors that will activate feed facets

-    profileContentLinks = new KDView
+    @profileContentLinks = new KDView
       lazyDomId : 'profile-content-links'

-    profileContentList = new KDView
+    @profileContentList = new KDView
       lazyDomId : 'profile-content-list'

     for type in CONTENT_TYPES
@@ -160,8 +224,8 @@
     @profileLogoView = new KDView
       lazyDomId: 'profile-koding-logo'
       click :=>
-        profilePersonalWrapperView.setClass 'slide-down'
-        profileContentWrapperView.setClass 'slide-down'
+        @profilePersonalWrapperView.setClass 'slide-down'
+        @profileContentWrapperView.setClass 'slide-down'
         @profileLogoView.setClass 'top'

         @profileLandingView.setClass 'profile-fading'
@@ -171,137 +235,81 @@

     @utils.wait => @profileLogoView.setClass 'animate'

-
-    # KD.remote.cacheable KD.config.profileEntryPoint, (err, user, name)=>
-
-
-    KD.remote.api.JAccount.one
-      "profile.nickname" : KD.config.profileEntryPoint
-    , (err, user, name)=>
-      if err then log err,user,name
-      unless err
-
-        profileUser = user
-        @emit 'DecorateStaticNavLinks', @getAllowedTypes profileUser
-
-        @avatarAreaIconMenu = new StaticAvatarAreaIconMenu
-          lazyDomId    : 'profile-buttons'
-          delegate     : @
-        , profileUser
-
-        @avatarAreaIconMenu.$('.static-profile-button').remove()
-
-        if user.getId() is KD.whoami().getId()
-
-          # reviving admin stuff
-
-          profileAdminCustomizeView = new KDView
-            lazyDomId : 'profile-admin-customize'
-
-          profileAdminCustomizeView.addSubView staticPageSettingsButton = new CustomLinkView
-            title : 'Customize'
-            cssClass : 'static-page-settings-button clean-gray'
-            click :(event)=>
-              @emit 'CustomizeLinkClicked'
-              event.stopPropagation()
-              event.preventDefault()
-
-          profileAdminCustomizeView.show()
-
-          profileAdminMessageView = new KDView
-            lazyDomId : 'profile-admin-message'
-
-          showPage = user.profile.staticPage?.show
-
-          profileAdminMessageView.addSubView disableLink = new CustomLinkView
-            title     : "#{if showPage is yes then 'Disable' else 'Enable'}"
-            cssClass  : 'message-disable'
-            click     : (event)=>
-              event?.stopPropagation()
-              event?.preventDefault()
-
-              if user.profile.staticPage?.show is yes
-                modal           = new KDModalView
-                  cssClass      : 'disable-static-page-modal'
-                  title         : 'Do you really want to disable your Public Page?'
-                  content       : """
-

-
Disabling this feature will disable other people
-                      from publicly viewing your profile. You will still be
-                      able to access the page yourself.

-
Do you want to continue?

-

-                    """
-                  buttons       :
-                    "Disable the Public Page" :
-                      cssClass  : 'modal-clean-red'
-                      callback  : =>
-                        modal.destroy()
-                        user.setStaticPageVisibility no, (err,res)=>
-                          if err then log err
-                          disableLink.updatePartial 'Enable this Public Page'
-                    Cancel      :
-                      cssClass  : 'modal-cancel'
-                      callback  : =>
-                        modal.destroy()
-              else
-                user.setStaticPageVisibility yes, (err,res)=>
-                  if err then log err
-                  disableLink.updatePartial 'Disable this Public Page'
-
-
-    @on 'CustomizeLinkClicked',=>
-      return if @customizeViewsAttached or KD.whoami().getId() isnt profileUser.getId()
-      @customizeViewsAttached = yes
-
-      @avatarAreaIconMenu.emit 'CustomizeLinkClicked'
-
-      # reviving customization
-
-      types = @getAllowedTypes profileUser
-
-      for type in CONTENT_TYPES
-        @navLinks[type].addSubView new StaticNavCheckBox
-          activityType : type
-          defaultValue : type in types
-          delegate     : @
-        , profileUser
-
-    @on 'ShowMoreButtonClicked', =>
-      @emit 'StaticProfileNavLinkClicked', 'CBlogPostActivity'
-
-    @on 'StaticProfileNavLinkClicked', (facets,isStatic=no)=>
-      @profileLoadingBar.setClass 'active'
-      @profileLoaderView.show()
-      facets = [facets] if 'string' is typeof facets
-
-      if profileUser
-        allowedTypes = @getAllowedTypes profileUser
-
-        blockedTypes = facets.reduce (acc, facet)->
-          acc.push facet unless facet in allowedTypes
-          return acc
-        , []
-
-        @emit 'DecorateStaticNavLinks', allowedTypes
-
-        if blockedTypes.length is 0
-          currentFacets = facets
-          appManager.tell 'Activity', 'fetchActivity',
-            originId : profileUser.getId()
-            facets : facets
-            bypass : yes
-          , (err, activities)=>
-            @refreshActivities err, activities, isStatic
-        else @emit 'BlockedTypesRequested', blockedTypes
-
-    @controller.on 'LazyLoadThresholdReached', =>
-      appManager.tell 'Activity', 'fetchActivity',
-        originId  : profileUser.getId()
-        facets    : currentFacets
-        to        : @controller.itemsOrdered.last.getData().meta.createdAt
-        bypass    : yes
-      , @bound "appendActivities"
+    console.timeEnd 'reviving page elements on pageload.'
+
+  reviveViewsOnUserLoad:(user)->
+
+    console.time 'reviving page elements on userload.'
+
+    @profileUser = user
+    @emit 'DecorateStaticNavLinks', @getAllowedTypes @profileUser
+
+    @avatarAreaIconMenu = new StaticAvatarAreaIconMenu
+      lazyDomId    : 'profile-buttons'
+      delegate     : @
+    , @profileUser
+
+    @avatarAreaIconMenu.$('.static-profile-button').remove()
+
+    if user.getId() is KD.whoami().getId()
+
+      # reviving admin stuff
+
+      profileAdminCustomizeView = new KDView
+        lazyDomId : 'profile-admin-customize'
+
+      profileAdminCustomizeView.addSubView staticPageSettingsButton = new CustomLinkView
+        title : 'Customize'
+        cssClass : 'static-page-settings-button clean-gray'
+        click :(event)=>
+          @emit 'CustomizeLinkClicked'
+          event.stopPropagation()
+          event.preventDefault()
+
+      profileAdminCustomizeView.show()
+
+      profileAdminMessageView = new KDView
+        lazyDomId : 'profile-admin-message'
+
+      showPage = user.profile.staticPage?.show
+
+      profileAdminMessageView.addSubView disableLink = new CustomLinkView
+        title     : "#{if showPage is yes then 'Disable' else 'Enable'}"
+        cssClass  : 'message-disable'
+        click     : (event)=>
+          event?.stopPropagation()
+          event?.preventDefault()
+
+          if user.profile.staticPage?.show is yes
+            modal           = new KDModalView
+              cssClass      : 'disable-static-page-modal'
+              title         : 'Do you really want to disable your Public Page?'
+              content       : """
+

+
Disabling this feature will disable other people
+                  from publicly viewing your profile. You will still be
+                  able to access the page yourself.

+
Do you want to continue?

+

+                """
+              buttons       :
+                "Disable the Public Page" :
+                  cssClass  : 'modal-clean-red'
+                  callback  : =>
+                    modal.destroy()
+                    user.setStaticPageVisibility no, (err,res)=>
+                      if err then log err
+                      disableLink.updatePartial 'Enable this Public Page'
+                Cancel      :
+                  cssClass  : 'modal-cancel'
+                  callback  : =>
+                    modal.destroy()
+          else
+            user.setStaticPageVisibility yes, (err,res)=>
+              if err then log err
+              disableLink.updatePartial 'Disable this Public Page'
+
+    console.timeEnd 'reviving page elements on userload.'

   repositionLogoView:->
     @profileLogoView.$().css
@@ -310,7 +318,6 @@
   appendActivities:(err,activities)->
     @controller.listActivities activities
     @controller.hideLazyLoader()
-

   refreshActivities:(err,activities,isStatic)->
     @profileContentView.$('.content-item').remove()
@@ -332,8 +339,8 @@
     @profileLoadingBar.unsetClass 'active'
     @profileLoaderView.hide()

-  getAllowedTypes:(profileUser)->
-      allowedTypes = profileUser.profile.staticPage?.showTypes or CONTENT_TYPES
+  getAllowedTypes:(@profileUser)->
+    allowedTypes = @profileUser.profile.staticPage?.showTypes or CONTENT_TYPES

 class StaticNavLink extends KDView


not relying on Id being defined for library listings

--- src/mpd.coffee
+++ src/mpd.coffee
@@ -310,11 +310,11 @@
       return

     # build list of tracks from msg
-    mpd_tracks = {}
-    current_track = {}
+    mpd_tracks = []
+    current_track = null
     flush_current_track = ->
-      return if current_track.Id == undefined
-      mpd_tracks[current_track.Id] = current_track
+      if current_track != null
+        mpd_tracks.push(current_track)
       current_track = {}
     for line in msg.split("\n")
       [key, value] = line.split(": ")
@@ -325,7 +325,7 @@

     # convert to our track format and add to cache
     track_table = @library.track_table
-    for id, mpd_track of mpd_tracks
+    for mpd_track in mpd_tracks
       track = @getOrCreateTrack(mpd_track.file)
       $.extend track,
         name: mpd_track.Title
@@ -354,10 +354,10 @@
       @addTracksToLibrary msg, (mpd_tracks) =>
         clearArray @playlist.item_list
         clearObject @playlist.item_table
-        for _, mpd_track of mpd_tracks
+        for mpd_track in mpd_tracks
           id = parseInt(mpd_track.Id)
           obj =
-            id: parseInt(id)
+            id: id
             track: @library.track_table[mpd_track.file]
             pos: @playlist.item_list.length
           @playlist.item_list.push obj
@@ -411,8 +411,8 @@
           @raiseEvent 'onStatusUpdate'
           return

-        # there's only one but we'll loop anyway since it's an object
-        for _, mpd_track of mpd_tracks
+        # there's either 0 or 1
+        for mpd_track in mpd_tracks
           id = parseInt(mpd_track.Id)
           pos = parseInt(mpd_track.Pos)


Add a default event handler configuration that passes a single extra argument containing the view models. [#161]

--- src/rivets.coffee
+++ src/rivets.coffee
@@ -441,6 +441,8 @@
 # overridden globally or local to a `Rivets.View` instance.
 Rivets.config =
   preloadData: true
+  handler: (fn, context, ev, binding) ->
+    fn.call context, ev, binding.view.models

 # Rivets.formatters
 # -----------------


- force string comparison between the input's value (which is always a string) and the data model's value

--- src/rivets.coffee
+++ src/rivets.coffee
@@ -274,7 +274,7 @@
       unbindEvent el, 'change', @currentListener
     routine: (el, value) ->
       if el.type is 'radio'
-        el.checked = el.value is value
+        el.checked = el.value?.toString() is value?.toString()
       else
         el.checked = !!value

@@ -286,7 +286,7 @@
       unbindEvent el, 'change', @currentListener
     routine: (el, value) ->
       if el.type is 'radio'
-        el.checked = el.value isnt value
+        el.checked = el.value?.toString() isnt value?.toString()
       else
         el.checked = !value


Move bidirectional binding/unbinding into proper context. Make sure that bypassed bindings with dependencies will get unbinded properly.

--- src/rivets.coffee
+++ src/rivets.coffee
@@ -78,6 +78,9 @@
       Rivets.config.adapter.subscribe @model, @keypath, @sync
       @sync() if Rivets.config.preloadData

+      if @isBidirectional()
+        bindEvent @el, 'change', @publish
+
     if @options.dependencies?.length
       for dependency in @options.dependencies
         if /^\./.test dependency
@@ -90,20 +93,18 @@

         Rivets.config.adapter.subscribe model, keypath, @sync

-    if @isBidirectional() and not @options.bypass
-      bindEvent @el, 'change', @publish

   # Unsubscribes from the model and the element.
   unbind: =>
     unless @options.bypass
       Rivets.config.adapter.unsubscribe @model, @keypath, @sync

-      if @options.dependencies?.length
-        for keypath in @options.dependencies
-          Rivets.config.adapter.unsubscribe @model, keypath, @sync
-
       if @isBidirectional()
         @el.removeEventListener 'change', @publish
+
+    if @options.dependencies?.length
+      for keypath in @options.dependencies
+        Rivets.config.adapter.unsubscribe @model, keypath, @sync

 # A collection of bindings built from a set of parent elements.
 class Rivets.View


Whenever a pane is added or removed, the editorUI is refreshed.

--- src/osx.coffee
+++ src/osx.coffee
@@ -3,6 +3,7 @@
 $ = require 'jquery'
 _ = require 'underscore'
 jscocoa = require 'jscocoa'
+Editor  = require 'editor'

 # Handles the UI chrome
 Chrome =
@@ -13,6 +14,9 @@
     el = document.createElement "div"
     el.setAttribute 'class', "pane " + position
     el.innerHTML = html
+
+    el.addEventListener('DOMNodeInsertedIntoDocument', Editor.resize, false);
+    el.addEventListener('DOMNodeRemovedFromDocument', Editor.resize, false);

     switch position
       when 'top', 'main'


fix(script): Fix typos

fix(script): Fix typos

--- src/script.coffee
+++ src/script.coffee
@@ -41,7 +41,7 @@
 parseDuration = (duration) ->
   return moment.utc(duration * 1000).format("HH:mm:ss")

-process = (timeEntries, amount, price) ->
+processTimeEntries = (timeEntries, amount, price) ->
   new Promise (resolve, reject) ->
     getUf().then (uf) ->
       limit = (amount / (uf * price)) * 3600
@@ -106,13 +106,13 @@
     message = ""
     toggl = getClient encryptor.decrypt user.toggl.api_token
     toggl.getTimeEntriesAsync(start, end).then (timeEntries) ->
-      process timeEntries, amount, price
+      processTimeEntries timeEntries, amount, price
     .then (data) ->
       message = data.message
       toggl.updateTimeEntriesTagsAsync data.teIds, tags, action
     .then () ->
       res.send message
-      welcome = "#{msg.message.user.name} close tasks successfull"
+      welcome = "#{res.message.user.name} close tasks successfull"
       robot.messageRoom(channel, "#{welcome}\n#{message}")
     .catch (err) ->
       res.reply "an error occurred in toggl"


Better sending strategy to avoid losing 1 datapoint each run

--- src/sender.coffee
+++ src/sender.coffee
@@ -6,16 +6,16 @@

   send: ->
     return unless @server.pending.length > 0
-    lines = @server.pending.join('\n') + '\n'
     conn = Net.connect @conf.carbonPort, @conf.carbonHost
     conn.addListener 'error', (error) =>
       @cli.debug "Connection error: #{error}"
     conn.on 'connect', () =>
       @cli.debug "Connected to #{@conf.carbonHost}:#{@conf.carbonPort}"
       try
-        @cli.debug "Sending lines: #{lines}"
-        conn.write lines
-        @server.pending = []
+        @cli.debug "Sending metrics"
+        while line = @server.pending.shift()
+          conn.write "#{line}\n"
+          @cli.debug "#{line}"
         @server.samplesRun = 0
       catch error
         @cli.error "Failed to send data: #{error}"


argh ... created with wrong permissions

argh ... created with wrong permissions


Deleting a marking updates species count

--- scripts/controllers/Classifier.coffee
+++ scripts/controllers/Classifier.coffee
@@ -124,6 +124,7 @@
 	deleteSelected: =>
 		index = i for marking, i in @picker.markers when marking.selected
 		@picker.markers[index].marking.destroy()
+		@classification.trigger 'change'

 	finishSpecies: =>
 		@picker.setDisabled true


JPermissionSet: simplify the constructor

--- workers/social/lib/social/models/group/permissionset.coffee
+++ workers/social/lib/social/models/group/permissionset.coffee
@@ -39,27 +39,31 @@
   KodingError = require '../../error'

   # coffeelint: disable=indentation
-  constructor:(data = {}, options = {}) ->
+  constructor: (data = {}, options = {}) ->
+
     super data
-    unless @isCustom
-      # initialize the permission set with some sane defaults:
-      { permissionDefaultsByModule } = require '../../traits/protected'
-      permissionsByRole = {}

-      options.privacy ?= 'public'
-      for own module, modulePerms of permissionDefaultsByModule
-        for own perm, roles of modulePerms
-          if roles.public? or roles.private?
-            roles = roles[options.privacy] ?= []
-          for role in roles
-            permissionsByRole[module]       ?= {}
-            permissionsByRole[module][role] ?= []
-            permissionsByRole[module][role].push perm
+    return  if @isCustom

-      @permissions = []
-      for own module, moduleRoles of permissionsByRole
-        for own role, modulePerms of moduleRoles
-          @permissions.push { module, role, permissions: modulePerms }
+    # initialize the permission set with some sane defaults:
+    { permissionDefaultsByModule } = require '../../traits/protected'
+    permissionsByRole = {}
+
+    options.privacy ?= 'public'
+    for own module, modulePerms of permissionDefaultsByModule
+      for own perm, roles of modulePerms
+        if roles.public? or roles.private?
+          roles = roles[options.privacy] ?= []
+        for role in roles
+          permissionsByRole[module]       ?= {}
+          permissionsByRole[module][role] ?= []
+          permissionsByRole[module][role].push perm
+
+    @permissions = []
+    for own module, moduleRoles of permissionsByRole
+      for own role, modulePerms of moduleRoles
+        @permissions.push { module, role, permissions: modulePerms }
+

   @wrapPermission = wrapPermission = (permission) ->
     [{ permission, validateWith: require('./validators').any }]


Add EventEmitter capabilities to the router

--- library/gearing/router.coffee
+++ library/gearing/router.coffee
@@ -25,6 +25,7 @@

 _ = require "underscore"
 logger = require "winston"
+events = require "events"
 colors = require "colors"
 util = require "util"

@@ -33,7 +34,7 @@
 # the supplied host, among other things. The exact matching logic
 # is up to the handlers that implement the corresponding methods.
 # This router just provides the infrastructure and boilerplating.
-module.exports.Router = class Router extends Object
+module.exports.Router = class Router extends events.EventEmitter

     # The method implements a middleware (for Connect) that looks
     # up the relevant routable and dispatches the request to the
@@ -68,8 +69,8 @@
         throw new Error(goneMatches) unless passMatches
         throw new Error(goneProcess) unless passProcess
         logger.info("Adding #{inspected} to the registry".magenta)
-        (@registry ?= []) push routable unless routable in @registry
-        return this
+        @registry ?= [] push routable unless routable in @registry
+        @emit("register", routable); this

     # Install the routable that should handle the requests that are
     # not handled via the registered routables. The routable has to
@@ -86,4 +87,4 @@
         throw new Error(goneMatches) unless passMatches
         throw new Error(goneProcess) unless passProcess
         logger.info("Installing #{inspected} as fallback".magenta)
-        @fallback = routable; return this
+        @fallback = routable; @emit("install", routable); this


Minor coding changes

Minor coding changes

--- library/nucleus/kernel.coffee
+++ library/nucleus/kernel.coffee
@@ -62,10 +62,10 @@
     # the kernel boots up. With no arguments it launches the stack.
     # This is a convenient way of running additions config routines.
     @configure: (explain, routine) ->
-        if arguments.length is 0
+        if arguments.length is 0 and _.isArray @$configure
             level = (e) -> logger.info "Configuring: %s", e
             fix = (o) -> (a...) -> level o.explain; o.routine a...
-        return async.series _.map(@$configure or [], fix)
+            return async.series _.map(@$configure, fix)
         assert _.isFunction(routine), "invalid config routine"
         assert _.isString(explain), "no explanation given"
         (@$configure ?= []).push


Fix the service removal off the queue!

Fix the service removal off the queue!

--- library/nucleus/scaled.coffee
+++ library/nucleus/scaled.coffee
@@ -87,7 +87,7 @@
         assert _.isString host = nconf.get "master:host"
         assert _.isNumber port = nconf.get "master:https"
         cmp = (exm) -> (srv) -> exm.uuid is srv.uuid or 0
-        remove = (srv) => _.remove @queueOfHttps, cmp(srv)
+        remove = (s) => assert _.remove @queueOfHttps, cmp(s)
         assert upgrade = @makeUpgraders @queueOfHttp, "https"
         assert registr = @makeRegistrar @queueOfHttps, "https"
         assert forward = @makeForwarder @queueOfHttps, "https"
@@ -110,7 +110,7 @@
         assert _.isString host = nconf.get "master:host"
         assert _.isNumber port = nconf.get "master:http"
         cmp = (exm) -> (srv) -> exm.uuid is srv.uuid or 0
-        remove = (srv) -> _.remove @queueOfHttp, cmp(srv)
+        remove = (s) => assert _.remove @queueOfHttp, cmp(s)
         assert upgrade = @makeUpgraders @queueOfHttp, "http"
         assert registr = @makeRegistrar @queueOfHttp, "http"
         assert forward = @makeForwarder @queueOfHttp, "http"


fix the doc

fix the doc

--- library/nucleus/scaled.coffee
+++ library/nucleus/scaled.coffee
@@ -56,7 +56,7 @@

     # This sets up the default identica for this kernel. It forms
     # an identica of a certain recommended format and populates it
-    # with data takes from the `PACKAGE` definition in a `Generic`
+    # with data takes from the `FRAMEWORK` definition in `Generic`
     # kernel. Refer to that kernel and to `identica` method there
     # for more information on semantics and the way of working it.
     @identica "#{@FRAMEWORK.name}@#{@FRAMEWORK.version}"


reduce default hub pool size to 50 (from 100)

--- src/smc-hub/hub.coffee
+++ src/smc-hub/hub.coffee
@@ -3061,7 +3061,7 @@
 connect_to_database = (opts) ->
     opts = defaults opts,
         error : 120
-        pool  : 100
+        pool  : 50
         cb    : required
     dbg = (m) -> winston.debug("connect_to_database: #{m}")
     if database? # already did this


init.coffee should use D.wins instead of wins

--- client/init.coffee
+++ client/init.coffee
@@ -23,7 +23,7 @@
       .on 'keydown', '*', 'ctrl+shift+=', D.zoomIn
     $('body').addClass "zoom#{prefs.zoom()}"
     prefs.zoom (z) ->
-      for _, w of wins
+      for _, w of D.wins
         $b = $ 'body', w.getDocument()
         $b.prop 'class', "zoom#{z} " + $b.prop('class').split(/\s+/).filter((s) -> !/^zoom-?\d+$/.test s).join ' '
         w.refresh()


Added more comments to the main.coffee.

Added more comments to the main.coffee.

--- client/main.coffee
+++ client/main.coffee
@@ -9,22 +9,28 @@
 #Template variables/functions
 min_posts = 1

-graduated = (tag, post) ->
-  return post.tags[tag].users.length >= 2
+#Graduated: Determines whether to group a post by a tag.  Would they make a good couple?  Have they earned each other?
+graduated = (tag, post) -> #The post/tag pair is graduated if the post is elegible to be grouped by that tag.
+  return post.tags[tag].users.length >= 2 # 2 or more users have tagged it with that tag.

+###
+#MakeGroups: Make a list of groups containing posts, for a given set of posts.
+#    Incubator group
+#    Tag group: group for each graduated tag.
+###
 makeGroups = (posts) ->
   groups = {'Incubator': {'posts': []}}
   for post in posts.fetch()
     tagCount = 0
-    placed = false
-    for tag,info of post.tags
-      if graduated(tag, post)
+    placed = false #post has not been placed into a group yet.
+    for tag of post.tags
+      if graduated(tag, post)
         if groups[tag]? #if there is a group for this tag
           groups[tag].posts.push(post) #add this post to the group's posts
         else
           groups[tag] = {'posts': [post]} #add a tag group with a "posts" field containing this post
-        placed = true
-      else if not placed
+        placed = true #this post has been placed
+      else if not placed #if the post isn't graduated and hasn't
         groups['Incubator'].posts.push(post)
         placed = true
       tagCount++


preserve original /status message

preserve original /status message

--- services/web/app/coffee/router.coffee
+++ services/web/app/coffee/router.coffee
@@ -272,9 +272,9 @@
 			res.send("hello")

 		webRouter.get '/status', (req,res)->
-			res.send("websharelatex is alive (web)")
+			res.send("web sharelatex is alive (web)")
 		apiRouter.get '/status', (req,res)->
-			res.send("websharelatex is alive (api)")
+			res.send("web sharelatex is alive (api)")

 		webRouter.get '/dev/csrf', (req, res) ->
 			res.send res.locals.csrfToken


added ga logging of starting free trial again

--- services/web/public/coffee/ide.coffee
+++ services/web/public/coffee/ide.coffee
@@ -65,7 +65,7 @@
 		$scope.chat = {}

 		$scope.startFreeTrial = (source) ->
-
+			ga?('send', 'event', 'subscription-funnel', 'upgraded-free-trial', source)
 			window.open("/user/subscription/new?planCode=student_free_trial_7_days")
 			$scope.startedFreeTrial = true


Read new dateFormat config setting

Read new dateFormat config setting

Set the blogFormatDate template helper to read the dateFormat config setting

--- client/boot.coffee
+++ client/boot.coffee
@@ -36,7 +36,7 @@
   return Blog.settings.language

 Template.registerHelper "blogFormatDate", (date) ->
-  moment(new Date(date)).format "MMM Do, YYYY"
+  moment(new Date(date)).format Blog.settings.dateFormat

 Template.registerHelper "blogFormatTags", (tags) ->
   return if !tags?


Fixup

Fixup

--- client/tawk.coffee
+++ client/tawk.coffee
@@ -5,7 +5,7 @@
 # Client Bus (all state prefixed with tawk/)
 ###############################################################################

-server       = 'statei://localhost'
+server       = 'state://tawk.space'

 window.statebus_ready or= []
 window.statebus_ready.push ->


Add emitter for data length on every call to filterAndSortData()

--- coffee/directives/fixtable.coffee
+++ coffee/directives/fixtable.coffee
@@ -231,6 +231,9 @@
 								scope.data.splice i, 1
 								break

+				# emit data length
+				scope.$emit 'fixtableDataLength', scope.data.length
+
 				# re-calculate dimensions since column widths may have changed
 				$timeout -> fixtable.setDimensions()


Core game completed

Core game completed

--- js/main.coffee
+++ js/main.coffee
@@ -22,11 +22,16 @@
 move = (board, direction) ->
   newBoard = buildBoard()
   for i in [0..3]
-    if direction == 'right' or 'left'
+    if direction is 'right' or direction is 'left'
       row = getRow(i, board)
       row = mergeCells(row, direction)
       row = collapseCells(row, direction)
-      setRow(row, i , newBoard)
+      setRow(row, i, newBoard)
+    else if direction is 'up' or direction is 'down'
+      column = getCol(i, board)
+      column = mergeCells(column, direction)
+      column = collapseCells(column, direction)
+      setCol(column, i, newBoard)

   newBoard

@@ -36,34 +41,40 @@
 setRow = (row, index, board) ->
   board[index] = row

-mergeCells = (row, direction) ->
+getCol = (c, board) ->
+  [board[0][c], board[1][c],board[2][c], board[3][c]]

-  merge = (row) ->
+setCol = (col, index, board) ->
+  for i in [0..3]
+    board[i][index] = col[i]
+
+mergeCells = (cell, direction) ->
+
+  merge = (cell) ->
     for a in [3...0]
       for b in [a-1..0]

-        if row[a] is 0 then break
-        else if row[a] == row[b]
-          row[a] *= 2
-          row[b] = 0
+        if cell[a] is 0 then break
+        else if cell[a] == cell[b]
+          cell[a] *= 2
+          cell[b] = 0
           break
-        else if row[b] isnt 0 then break
-    row
+        else if cell[b] isnt 0 then break
+    cell

-  if direction is 'right'
-    merge row
-  else if direction is 'left'
-    merge(row.reverse()).reverse()
+  if direction is 'right' or direction is 'down'
+    merge cell
+  else if direction is 'left' or direction is 'up'
+    merge(cell.reverse()).reverse()

-collapseCells = (row, direction) ->
-  row = row.filter (ele) -> ele isnt 0
-  if direction is 'right'
-    while row.length < 4
-      row.unshift 0
-  else if direction is 'left'
-    while row.length < 4
-      row.push 0
-  row
+collapseCells = (cell, direction) ->
+  cell = cell.filter (ele) -> ele isnt 0
+  while cell.length < 4
+    if direction is 'right' or direction is 'down'
+      cell.unshift 0
+    else if direction is 'left' or direction is 'up'
+      cell.push 0
+  cell

 moveIsValid = (originalBoard, newBoard) ->
   for row in [0..3]
@@ -79,7 +90,6 @@
   true

 noValidMove = (board) ->
-  direction = 'right' #FIXME: Handle other directions
   newBoard = move(board, direction)
   if moveIsValid(board, newBoard)
     return false
@@ -139,7 +149,6 @@
         else
           # show board
           showBoard(@board)
-
       else
         console.log "Invalid"


implementing tests

implementing tests


Add encoding getter and setter

Add encoding getter and setter

--- src/text-buffer.coffee
+++ src/text-buffer.coffee
@@ -303,12 +303,22 @@

     if filePath
       @file = new File(filePath)
+      if encoding = @getEncoding()
+        @file.setEncoding(encoding)
       @subscribeToFile()
     else
       @file = null

     @emitter.emit 'did-change-path', @getPath()
     @emit "path-changed", this
+
+  # Public: Sets the encoding for this buffer.
+  #
+  # * `encoding` The {String} encoding to use such as 'utf8'
+  setEncoding: (@encoding) -> @file?.setEncoding(@encoding)
+
+  # Public: Returns the {String} encoding of this buffer.
+  getEncoding: -> @encoding ? @file.getEncoding()

   # Public: Get the path of the associated file.
   #


Activity: some dummy views added

Activity: some dummy views added

--- client/Social/Activity/ContentDisplays/activitysideviews.coffee
+++ client/Social/Activity/ContentDisplays/activitysideviews.coffee
@@ -1,6 +1,8 @@
 class ActivitySideView extends JView

-  constructor:(options={}, data)->
+  constructor:(options = {}, data)->
+
+    options.tagName = 'section'

     super options, data

@@ -24,10 +26,8 @@

   pistachio:->
     """
-

-
#{@getOption 'title'}{{> @showAllLink}}

-      {{> @tickerListView}}
-

+
#{@getOption 'title'}{{> @showAllLink}}

+    {{> @tickerListView}}
     """

 class UserGroupList extends ActivitySideView
@@ -54,6 +54,67 @@
       if items.length - 1
         @parent.emit 'TopOffsetShouldBeFixed'
         @show()
+
+class DummyUsers extends ActivitySideView
+
+  skip = -3
+
+  constructor:(options={}, data)->
+
+    {entryPoint} = KD.config
+
+    if entryPoint?.type is "group" then group = entryPoint.slug else group = "koding"
+
+    @itemClass       = MembersListItemView
+    options.title    = if group is "koding" then "Active users" else "New Members"
+    options.cssClass = "active-users"
+
+    super options, data
+
+    @showAllLink = new KDCustomHTMLView
+      tagName : "a"
+      partial : "show all"
+      cssClass: "show-all-link hidden"
+      click   : (event) ->
+        KD.singletons.router.handleRoute "/Members"
+        KD.mixpanel "Show all members, click"
+    , data
+    KD.singletons.groupsController.ready =>
+      skip += 3
+      currentGroup = KD.singletons.groupsController.getCurrentGroup()
+      currentGroup.fetchNewestMembers {}, {limit : 3, skip}, @bound 'renderItems'
+
+
+class DummyTopics extends ActivitySideView
+
+  skip = -3
+
+  constructor:(options={}, data)->
+
+    @itemClass       = ActiveTopicItemView
+    options.title    = "Popular topics"
+    options.cssClass = "active-topics"
+
+    super options, data
+
+    {entryPoint} = KD.config
+    if entryPoint?.type is "group" then group = entryPoint.slug else group = "koding"
+
+    @showAllLink = new KDCustomHTMLView
+
+    skip += 3
+
+    KD.remote.api.JTag.some {group},
+      limit  : 3
+      skip   : skip
+      sort   : "counts.followers" : -1
+    , (err, topics)=>
+      if err or topics.length is 0
+        @hide()
+      else
+        @renderItems err, topics
+
+

 class ActiveUsers extends ActivitySideView


minor

minor

--- client/landing/app/MainApp/maincontroller/maincontroller.coffee
+++ client/landing/app/MainApp/maincontroller/maincontroller.coffee
@@ -26,19 +26,18 @@
     # will be deprecated soon.
     window.appManager = new ApplicationManager

-    KD.registerSingleton "appManager", appManager
-    KD.registerSingleton "mainController", @
-    KD.registerSingleton "kiteController", new KiteController
-    KD.registerSingleton "vmController", new VirtualizationController
-    KD.registerSingleton "contentDisplayController", new ContentDisplayController
-    KD.registerSingleton "notificationController", new NotificationController
-    KD.registerSingleton "localStorageController", new LocalStorageController
+    KD.registerSingleton "mainController",            this
+    KD.registerSingleton "appManager",                appManager
+    KD.registerSingleton "kiteController",            new KiteController
+    KD.registerSingleton "vmController",              new VirtualizationController
+    KD.registerSingleton "contentDisplayController",  new ContentDisplayController
+    KD.registerSingleton "notificationController",    new NotificationController
+    KD.registerSingleton "paymentController",         new NotificationController
+    KD.registerSingleton "linkController",            new LinkController
+    KD.registerSingleton 'router',           router = new KodingRouter location.pathname
+
+    # KD.registerSingleton "localStorageController", new LocalStorageController
     # KD.registerSingleton "fatih", new Fatih
-
-    KD.registerSingleton "linkController", new LinkController
-
-    router = new KodingRouter location.pathname
-    KD.registerSingleton 'router', router

     appManager.create 'Groups', (groupsController)->
       KD.registerSingleton "groupsController", groupsController
@@ -48,7 +47,7 @@

     @ready =>
       router.listen()
-      KD.registerSingleton "activityController", new ActivityController
+      KD.registerSingleton "activityController",   new ActivityController
       KD.registerSingleton "kodingAppsController", new KodingAppsController
       @emit 'AppIsReady'
       @emit 'FrameworkIsReady'


client: adds 'beta' tag for providers

client: adds 'beta' tag for providers

--- client/stack-editor/lib/onboarding/providerselectionview.coffee
+++ client/stack-editor/lib/onboarding/providerselectionview.coffee
@@ -21,16 +21,25 @@
       'aws', 'vagrant', 'azure', 'digitalocean', 'googlecloud', 'rackspace'
     ]
     enabledProviders = ['aws', 'vagrant']
+    betaProviders = ['vagrant']

     @providers = new kd.CustomHTMLView { cssClass: 'providers box-wrapper clearfix' }

     providers.forEach (provider) =>
       extraClass = 'coming-soon'
       label      = 'Coming Soon'
+      beta       = ''
+      betaLabel  = ''

       if provider in enabledProviders
         extraClass = ''
         label      = ''
+        beta       = ''
+        betaLabel  = ''
+        if provider in betaProviders
+          beta       = 'beta'
+          betaLabel  = 'BETA'
+

       @providers.addSubView providerView = new kd.CustomHTMLView
         cssClass : "provider box #{extraClass} #{provider}"
@@ -38,6 +47,7 @@
         partial  : """

#{label}

+
#{betaLabel}

         """
         click: =>
           return if extraClass is 'coming-soon'


Modified gh-pages

Modified gh-pages

--- source/javascripts/gh-pages.js.coffee
+++ source/javascripts/gh-pages.js.coffee
@@ -71,7 +71,8 @@

Join to contribution

Fork me on
-          Github
+          Github

Future works


NEVER GIVE UP

NEVER GIVE UP

--- tests/loud_test.coffee
+++ tests/loud_test.coffee
@@ -18,7 +18,7 @@
       expect(room.robot.brain.get('louds')).to.eql ['WHO THE HECK ARE YOU', 'WHAT IS GOING ON HERE', 'HELP I AM TRAPPED IN A UNIT TEST']

     it 'should support funny characters', ->
-     room.user.say 'alice',   '"FOO"'
+      room.user.say 'alice',   '"FOO"'
       room.user.say 'bob',     'FOO+'
       room.user.say 'charlie', 'FOO-'
       room.user.say 'alice',   'FOO!'


reimplementing flash / cors XD requests

reimplementing flash / cors XD requests

--- src/sdk.coffee
+++ src/sdk.coffee
@@ -11,6 +11,7 @@
   initialize: (options={}) ->
     this.accessToken(options["access_token"])
     this.options[key] = value for own key, value of options
+    this.options.flashXHR ||= (new XMLHttpRequest()).withCredentials == undefined
     this

   hostname: (subdomain) ->
@@ -22,15 +23,14 @@
 #################
 # AUTHORIZATION #
 #################
-
+
   connect: (options) ->
     options.client_id    ||= SC.options.client_id
     options.redirect_uri ||= SC.options.redirect_uri
     SC.connectCallbacks.success    = options.connected
     SC.connectCallbacks.error      = options.error
     SC.connectCallbacks.general    = options.callback
-
-
+
     if options.client_id && options.redirect_uri
       uri = new SC.URI("https://" + this.hostname() + "/connect/?")
       uri.query =
@@ -42,7 +42,7 @@
       SC._popupWindow = SC.Helper.openCenteredPopup uri.toString(), 456, 510
     else
       throw "Either client_id and redirect_uri (for user agent flow) must be passed as an option"
-
+
   connectCallback: ->
     popupWindow = SC._popupWindow
     popupLocation = popupWindow.location.toString()
@@ -52,17 +52,16 @@
     if error == "redirect_uri_mismatch"
       popupWindow.document.body.innerHTML = "
The redirect URI '"+ popupLocation +"' you specified does not match the one that is configured in your SoundCloud app.
 You can fix this in your app settings on SoundCloud"
       return false
-
+
     popupWindow.close()
     if error
       SC._trigger("error", error)
     else
       SC.accessToken(uri.fragment.access_token);
       SC._trigger("success")
-
+
     SC._trigger("general", error)
-
-
+
   disconnect: ->
     this.accessToken(null);

@@ -130,22 +129,53 @@
     query ||= {}
     uri = SC.prepareRequestURI(path, query)
     uri.query.format = "json"
-    #data = uri.encodeParams(uri.query) #uri.query = {}
-
-    this.whenXDMReady =>
-      crossdomain.ajax({
-        type: method
-        url:  uri.toString()
-        #data: data
-        headers:
-          "Content-Type": "application/x-www-form-urlencoded"
-        error: (response) ->
-          obj = JSON.parse(response)
-          callback(obj)
-        success: (response) ->
-          obj = JSON.parse(response)
-          callback(obj)
-      })
+
+    if SC.options.flashXHR
+      uri.query["_status_code_map[400]"] = 200
+      uri.query["_status_code_map[401]"] = 200
+      uri.query["_status_code_map[403]"] = 200
+      uri.query["_status_code_map[404]"] = 200
+      uri.query["_status_code_map[422]"] = 200
+      uri.query["_status_code_map[500]"] = 200
+      uri.query["_status_code_map[503]"] = 200
+      uri.query["_status_code_map[504]"] = 200
+
+    if method == "PUT" || method == "DELETE"
+      uri.query._method = method
+      method = "POST"
+
+    if method != "GET"
+      data = uri.encodeParams(uri.query)
+      uri.query = {}
+
+    handleResponse = (responseText, xhr) ->
+      json = SC.Helper.JSON.parse(responseText)
+      error = null
+
+      if !json
+        if xhr
+          error = {message: "HTTP Error: " + xhr.status}
+        else
+          error = {message: "Unknown error"}
+      else if json.errors
+        error = { message: json.errors && json.errors[0].error_message }
+
+      callback(json, error)
+
+    if SC.options.flashXHR
+      this.whenRecordingReady ->
+        Recorder.request method, uri.toString(), data, handleResponse
+    else
+      this._request method, uri.toString(), data, handleResponse
+
+  _request: (method, uri, data, callback) ->
+    request = new XMLHttpRequest();
+    request.open(method, uri.toString(), true);
+    request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
+    request.onreadystatechange = (e) ->
+      if(e.target.readyState == 4)
+        callback(e.target.responseText, e.target)
+    request.send(data);

   post:   (path, query, callback) ->
     this.request("POST",   path, query, callback)


Fix DomainEventService specs

Fix DomainEventService specs

--- spec/domain_event_service_spec.coffee
+++ spec/domain_event_service_spec.coffee
@@ -1,61 +1,52 @@
-describe.skip 'DomainEventService', ->
+describe 'DomainEventService', ->

   sinon      = require 'sinon'
   expect     = require 'expect.js'
   eventric   = require 'eventric'

   DomainEventService = eventric 'DomainEventService'
+  EventStore         = eventric 'MongoDBEventStore'

   sandbox = null
+  eventStore = null
+  domainEventService = null
   beforeEach ->
     sandbox = sinon.sandbox.create()
+    eventStore = sinon.createStubInstance EventStore
+    eventStore.save.yields null
+    domainEventService = new DomainEventService eventStore

   afterEach ->
     sandbox.restore()

   it 'should have extended Backbone.Events', ->
-    expect(DomainEventService.trigger).to.be.ok()
+    expect(domainEventService.trigger).to.be.ok()

-  describe '#handle', ->
+  describe '#saveAndTrigger', ->

     domainEvent = null
     beforeEach ->
       domainEvent =
         name: 'testMethod'
-        metaData:
+        aggregate:
           id: 1
           name: 'Example'
-        _changed:
-          props:
-            name: 'John'
+          changed:
+            props:
+              name: 'John'

-    it 'should call _applyChanges with given DomainEvents on active matching ReadModels', ->
-      class ExampleReadModel
-        _applyChanges: sinon.stub()
+    it 'should tell the EventStore to save the DomainEvent', (done) ->
+      domainEventService.saveAndTrigger [domainEvent], (err) ->
+        expect(eventStore.save.calledOnce).to.be.ok()
+        done()

-      exampleReadModel = new ExampleReadModel
-
-      DomainEventService._handlers =
-        'Example':
-          1: [
-            exampleReadModel
-          ]
-
-      DomainEventService.handle [domainEvent]
-
-      expect(exampleReadModel._applyChanges.calledWith domainEvent._changed).to.be.ok()
-
-    it 'should trigger the given DomainEvent', ->
-      triggerSpy = sandbox.spy DomainEventService, 'trigger'
-      DomainEventService.handle [domainEvent]
-      expect(triggerSpy.calledWith 'DomainEvent', domainEvent).to.be.ok()
-      expect(triggerSpy.calledWith 'Example', domainEvent).to.be.ok()
-      expect(triggerSpy.calledWith 'Example/1', domainEvent).to.be.ok()
-      expect(triggerSpy.calledWith 'Example:testMethod', domainEvent).to.be.ok()
-      expect(triggerSpy.calledWith 'Example:testMethod/1', domainEvent).to.be.ok()
-
-    it 'should store the DomainEvent into a local cache', ->
-      storeInCacheSpy = sandbox.spy DomainEventService, '_storeInCache'
-      DomainEventService.handle [domainEvent]
-      expect(storeInCacheSpy.calledWith domainEvent).to.be.ok()+    it 'should trigger the given DomainEvent', (done) ->
+      triggerSpy = sandbox.spy domainEventService, 'trigger'
+      domainEventService.saveAndTrigger [domainEvent], (err) ->
+        expect(triggerSpy.calledWith 'DomainEvent', domainEvent).to.be.ok()
+        expect(triggerSpy.calledWith 'Example', domainEvent).to.be.ok()
+        expect(triggerSpy.calledWith 'Example/1', domainEvent).to.be.ok()
+        expect(triggerSpy.calledWith 'Example:testMethod', domainEvent).to.be.ok()
+        expect(triggerSpy.calledWith 'Example:testMethod/1', domainEvent).to.be.ok()
+        done()


add file-icons to atom

add file-icons to atom

--- atom/packages.cson
+++ atom/packages.cson
@@ -1,3 +1,4 @@
 packages: [
+  "file-icons"
   "package-sync"
 ]


Set ghc process encoding

Set ghc process encoding

--- lib/ghci.coffee
+++ lib/ghci.coffee
@@ -35,9 +35,11 @@
       @process = new BufferedProcess
         command: command
         args: args
-        options: {cwd}
+        options:
+          cwd: cwd
+          encoding: 'utf8'
         stdout: (output) =>
-          lines = output.toString().split(EOL).slice(0, -1) #last line is empty
+          lines = output.split(EOL).slice(0, -1) #last line is empty
           lines = lines.map (line) ->
             if line.length > 10000
               line.slice(0, 10000) + '...'


Use a config schema

Use a config schema

Closes #11
Closes #13

--- lib/init.coffee
+++ lib/init.coffee
@@ -1,6 +1,10 @@
 module.exports =
-	configDefaults:
-		scalacExecutablePath: ''
-		scalacOptions: '-Xlint'
+	config:
+		scalacExecutablePath:
+			type: 'string'
+			default: ''
+		scalacOptions:
+			type: 'string'
+			default: '-Xlint'

 	activate: -> console.log('activate linter-scalac')


Added exists and isnull query options

Added exists and isnull query options

--- server/controllers/helper/querySplitter.coffee
+++ server/controllers/helper/querySplitter.coffee
@@ -26,8 +26,16 @@
       when "gte"
         result =
           $gte: splits2[1]
+      when "exists"
+        result =
+          $exists: (splits2[1] == "true") ? true : false
   else
     result = split
+
+    switch split
+      when "isnull"
+        result =
+          $type: 10

   result

@@ -44,4 +52,3 @@
 module.exports =
   processSplit: processSplit
   processSplits: processSplits
-


apiHelpers: send default error if err not in a standard apiError

--- servers/lib/server/handlers/api/helpers.coffee
+++ servers/lib/server/handlers/api/helpers.coffee
@@ -11,8 +11,9 @@

 sendApiError = (res, error) ->

-  response = { error }
-  return res.status(error.status).send response
+  response  = { error }
+  response ?= 'API Error'
+  return res.status(error.status ? 403).send response

 sendApiResponse = (res, data) ->


Allow 'Save All' files to work as well as guarding against multiple transpiles when a text file is working in split screen mode.

--- lib/main.coffee
+++ lib/main.coffee
@@ -1,4 +1,6 @@
 {CompositeDisposable} = require 'atom'
+
+INTERFILESAVETIME = 1000

 module.exports =
   config: require './config'
@@ -8,6 +10,7 @@
     # track any file save events and transpile if babel
     @disposable = new CompositeDisposable
     @textEditors = {}
+    @fileSaveTimes = {}

     @disposable.add atom.project.onDidChangePaths =>
       @transpiler.stopUnusedTasks()
@@ -15,15 +18,22 @@
     @disposable.add atom.workspace.observeTextEditors (textEditor) =>
       @textEditors[textEditor.id] = new CompositeDisposable
       @textEditors[textEditor.id].add textEditor.onDidSave (event) =>
-        if atom.workspace.getActiveTextEditor().id is textEditor.id and
-        textEditor.getGrammar().packageName is 'language-babel'
-          @transpiler.transpile(event.path, textEditor)
+        if textEditor.getGrammar().packageName is 'language-babel'
+          filePath = textEditor.getPath()
+          lastSaveTime = @fileSaveTimes[filePath]
+          @fileSaveTimes[filePath] = Date.now()
+          if not lastSaveTime? + INTERFILESAVETIME < @fileSaveTimes[filePath]
+            @transpiler.transpile(filePath, textEditor)
       @textEditors[textEditor.id].add textEditor.onDidDestroy () =>
+        filePath = textEditor.getPath()
+        if @fileSaveTimes[filePath]? then delete@fileSaveTimes[filePath]
         @textEditors[textEditor.id].dispose()
         delete @textEditors[textEditor.id]

   deactivate: ->
     @disposable.dispose()
     for id, disposeable of @textEditors
-      disposeable.dispose()
+      disposeable.dispose()
+    for filePath, val of @fileSaveTimes
+      delete@fileSaveTimes[filePath]
     @transpiler.stopAllTranspilerTask()


Use Atom APIs for getting editor and position (#110)

--- lib/main.coffee
+++ lib/main.coffee
@@ -188,10 +188,16 @@
       return token + text + token

   _getEditorAndPosition: (event) ->
-    editor = event.target.model
+    # editor = event.target.model
+    editor = atom.workspace.getActiveTextEditor()
     if editor
-      position = editor.cursors[0].marker.oldHeadBufferPosition
-      return {editor, position}
+      # position = editor.cursors[0].marker.oldHeadBufferPosition
+      positions = editor.getCursorBufferPositions()
+      if positions
+        position = positions[0]
+        return {editor, position}
+      else
+        event.abortKeyBinding()
     else
       event.abortKeyBinding()


#update #16

#update #16

--- lib/main.coffee
+++ lib/main.coffee
@@ -13,7 +13,6 @@

 # Report crashes to our server.
 require('crash-reporter').start();
-console.log "Joo"

 # Report crashes to our server.
 # require('crash-reporter').start()
@@ -25,6 +24,7 @@
 flashPath = packageFile.flash.path
 flashVersion = packageFile.flash.version
 if process.platform == 'win32'
+  console.log "Joo"
   flashPath = "C:\\Users\\wii\\AppData\\Local\\Google\\Chrome\\User\ Data\\PepperFlash\\19.0.0.226\\pepflashplayer.dll"

 console.log "use ppapi-flash-path: #{flashPath}"


revert to exec

revert to exec

--- lib/main.coffee
+++ lib/main.coffee
@@ -1,7 +1,7 @@
 meta = require '../package.json'

 # Dependencies
-{spawn} = require 'child_process'
+{exec} = require 'child_process'
 os = require 'os'

 module.exports = NslCore =
@@ -48,46 +48,44 @@
     if script? and scope.startsWith 'source.nsl'
       editor.save() if editor.isModified()

-      @getPath (data) ->
+      @getPath (javaBin) ->
         nslJar  = atom.config.get('language-nsl.pathToJar')

         if not nslJar
           atom.notifications.addError("**#{meta.name}**: no valid `nsL.jar` was specified in your config", dismissable: false)
           return

-        defaultArguments = ["-jar", nslJar]
+        defaultArguments = ["java", "-jar", "\"#{nslJar}\""]
         customArguments = atom.config.get('language-nsl.customArguments').trim().split(" ")
+        customArguments.push("\"#{script}\"")

-        if os.platform() is 'win32'
-          customArguments.push("\"#{script}\"")
-        else
-          customArguments.push(script)
+        nslCmd = defaultArguments.concat(customArguments).join(" ")

-        args = defaultArguments.concat(customArguments)
-        nslCmd = spawn('java', args)
+        exec nslCmd, (error, stdout, stderr) ->
+          if error or stderr
+            if error
+              atom.notifications.addError("Transpiling failed", detail: error, dismissable: true)

-        nslCmd.stderr.on 'data', (data) ->
-          atom.notifications.addError("Transpiling failed", detail: data, dismissable: true)
-          return
+            if stderr
+              atom.notifications.addError("Transpiling failed", detail: stderr, dismissable: true)

-        nslCmd.stdout.on 'data', (data) ->
-          atom.notifications.addSuccess("Transpiled successfully", detail: data, dismissable: false)
-          return
+            return
+
+          atom.notifications.addSuccess("Transpiled successfully", detail: stdout, dismissable: false)
     else
       # Something went wrong
       atom.beep()

   getPath: (callback) ->
     if os.platform() is 'win32'
-      whichCmd = spawn('where', ['java'])
+      whichJava  = "where java"
     else
-      whichCmd = spawn('which', ['java'])
+      whichJava  = "which java"

     # Find Java
-    whichCmd.stderr.on 'data', (data) ->
-      atom.notifications.addError("**#{meta.name}**: Java is not in your `PATH` [environmental variable](http://superuser.com/a/284351/195953)", dismissable: true)
+    exec whichJava, (error, stdout, stderr) ->
+      if error isnt null
+        atom.notifications.addError("**#{meta.name}**: Java is not in your `PATH` [environmental variable](http://superuser.com/a/284351/195953)", dismissable: true)
+      else
+        callback stdout
       return
-
-    whichCmd.stdout.on 'data', (data) ->
-      callback data
-      return


CoffeeScript tidying

CoffeeScript tidying

--- lib/main.coffee
+++ lib/main.coffee
@@ -60,10 +60,10 @@

       # save the {editor} into a map
       editorId = editor.id
-      spellCheckViews[editorId] = {}
-      spellCheckViews[editorId]['view'] = spellCheckView
-      spellCheckViews[editorId]['active'] = true
-      spellCheckViews[editorId]['editor'] = editor
+      spellCheckViews[editorId] =
+        view: spellCheckView
+        active: true
+        editor: editor
       @viewsByEditor.set editor, spellCheckView

   deactivate: ->


Ignore examined if they overlap with an existing path

--- lib/main.coffee
+++ lib/main.coffee
@@ -618,7 +618,8 @@
     nodes = _.flatten([_.values(@open), _.values(@closed)])
     withParents = _.select nodes, (e) -> e.parent?
     paths = _.map withParents, (e) -> [e.parent.pos, e.pos]
-    examined = _.map @examined, (e) -> [e.parent.pos, e.pos]
+    examined = _.reject @examined, (e) -> _.some withParents, (p) -> p.key is e.key
+    examined = _.map examined, (e) -> [e.parent.pos, e.pos]

     finalPath = []
     if @path


findCodeBlock: Selection text ending in column 0

* Accounted for the case when the selection text ends in column 0.

--- lib/main.coffee
+++ lib/main.coffee
@@ -267,6 +267,8 @@
         if selectedText != ''
             selectedRange = @editor.getSelectedBufferRange()
             endRow = selectedRange.end.row
+            if selectedRange.end.column is 0
+                endRow = endRow - 1
             while @blank(endRow)
                 endRow = endRow - 1
             return [selectedText, endRow]


Conditionally remove settingsView

Conditionally remove settingsView

--- lib/main.coffee
+++ lib/main.coffee
@@ -39,7 +39,7 @@
       'settings-view:check-for-package-updates': -> atom.workspace.open("#{configUri}/updates")

   deactivate: ->
-    settingsView.remove()
+    settingsView?.remove()
     settingsView = null

   consumeStatusBar: (statusBar) ->


Change from pure to bootstrap

Change from pure to bootstrap

--- javascripts/components/Layout.coffee
+++ javascripts/components/Layout.coffee
@@ -5,7 +5,8 @@

 module.exports = React.createClass
   render: ->
-    R.div {className: 'pure-g'},
-      R.nav {className: 'pure-u-1'},
-        new Nav(null),
-      @props.view
+    R.div null,
+      R.nav null,
+        new Nav()
+      R.div {className: 'col-md-12'},
+        @props.view


Refactoring: use instance instead of class methods. Improves letWinnerWinMatchesAgainstCompetitorsWhichLoseAgainstLoser to call appointWinnerOfMatch with otherLoserId instead of loserId.

--- app/assets/javascripts/voluntary/dom_manipulation/competitive_list.js.coffee
+++ app/assets/javascripts/voluntary/dom_manipulation/competitive_list.js.coffee
@@ -1,106 +1,112 @@
-window.Voluntary or= {}; window.Voluntary.DomManipulation or= {}
-
-window.Voluntary.DomManipulation.CompetitiveList = class CompetitiveList
+class @CompetitiveList
+  competitiveListOptions: []
+  competitors: []
+  competitorsOfCompetitor: {}
+  defeatedCompetitorsByCompetitor: {}
+  outmatchedCompetitorsByCompetitor: {}
+  matchesLeft: 0
+  currentMatch: null
+  currentMatchIndex: 0
+
   constructor: (options) ->
-    window.competitiveListOptions = options
-    window.competitiveListOptions ||= {}
-
-    $(document.body).on "click", ".competitive_list_start_link", (event) ->
+    @competitiveListOptions = options
+    @competitiveListOptions ||= {}
+
+    $(document.body).on "click", ".competitive_list_start_link", (event) =>
       event.preventDefault()
-      window.Voluntary.DomManipulation.CompetitiveList.start()
-
-    $(document.body).on "click", ".cancel_tournament_button", (event) ->
+      @start()
+
+    $(document.body).on "click", ".cancel_tournament_button", (event) =>
       event.preventDefault()
-      window.Voluntary.DomManipulation.CompetitiveList.cancelTournament()
-
-    $(document.body).on "click", ".select_winner_button", (event) ->
+      @cancelTournament()
+
+    $(document.body).on "click", ".select_winner_button", (event) =>
       event.preventDefault()
-      window.Voluntary.DomManipulation.CompetitiveList.appointWinnerOfMatchByInput()
-
-  @start: () ->
+      @appointWinnerOfMatchByInput()
+
+  start: () ->
     matchesAlreadyExist = false
     window.matches ||= []

     if window.matches.length > 0
       matchesAlreadyExist = true

-    window.competitors = jQuery.map($('.competitive_list li'), (c) ->
+    @competitors = jQuery.map($('.competitive_list li'), (c) ->
       return $(c).data('id')
     )
-    window.competitorsOfCompetitor = {}
-    window.defeatedCompetitorsByCompetitor = {}
-    window.outmatchedCompetitorsByCompetitor = {}
-    window.matchesWon = {}
+    @competitorsOfCompetitor = {}
+    @defeatedCompetitorsByCompetitor = {}
+    @outmatchedCompetitorsByCompetitor = {}

     if matchesAlreadyExist
       if confirm('Remove previous results and start over?')
         window.matches = []
       else
-        window.Voluntary.DomManipulation.CompetitiveList.removeMatchesOfNonExistingCompetitors()
-
-    window.Voluntary.DomManipulation.CompetitiveList.generateMatches()
+        @removeMatchesOfNonExistingCompetitors()
+
+    @generateMatches()

     matchesWithoutWinner = jQuery.map(window.matches, (m) ->
       if m['winner_competitor'] == undefined
         return m
     )

-    window.matchesLeft = matchesWithoutWinner.length
-
-    if window.Voluntary.DomManipulation.CompetitiveList.nextMatch()
+    @matchesLeft = matchesWithoutWinner.length
+
+    if @nextMatch()
       $('#bootstrap_modal').modal('show')

-  @removeMatchesOfNonExistingCompetitors: () ->
-    $.each window.matches, (index, match) ->
-      notExistingCompetitors = jQuery.map(match['competitors'], (c) ->
-        if $.inArray(c, window.competitors) == -1
+  removeMatchesOfNonExistingCompetitors: () ->
+    $.each window.matches, (index, match) =>
+      notExistingCompetitors = jQuery.map(match['competitors'], (c) =>
+        if $.inArray(c, @competitors) == -1
           return c
       )

       if notExistingCompetitors.length > 0
-        window.matches = window.Voluntary.DomManipulation.CompetitiveList.removeItemFromArray(window.matches, match)
+        window.matches = @removeItemFromArray(window.matches, match)
       else
-        window.competitorsOfCompetitor[match['competitors'][0]] ||= []
-        window.competitorsOfCompetitor[match['competitors'][0]].push match['competitors'][1]
-        window.competitorsOfCompetitor[match['competitors'][1]] ||= []
-        window.competitorsOfCompetitor[match['competitors'][1]].push match['competitors'][0]
+        @competitorsOfCompetitor[match['competitors'][0]] ||= []
+        @competitorsOfCompetitor[match['competitors'][0]].push match['competitors'][1]
+        @competitorsOfCompetitor[match['competitors'][1]] ||= []
+        @competitorsOfCompetitor[match['competitors'][1]].push match['competitors'][0]

         unless match['winner_competitor'] == undefined
-          loserId = window.Voluntary.DomManipulation.CompetitiveList.otherCompetitorOfMatch(match, match['winner_competitor'])
-          window.Voluntary.DomManipulation.CompetitiveList.incrementMatchesWon(match['winner_competitor'], loserId)
+          loserId = @otherCompetitorOfMatch(match, match['winner_competitor'])
+          @updateDefeatedAndOutmatchedCompetitorsByCompetitor(match['winner_competitor'], loserId)

-  @removeItemFromArray: (array, item) ->
+  removeItemFromArray: (array, item) ->
     list = []

-    $.each array, (index, workingItem) ->
+    $.each array, (index, workingItem) =>
       unless JSON.stringify(workingItem) == JSON.stringify(item)
         list.push workingItem

     return list

-  @generateMatches: () ->
-    $.each window.competitors, (index, competitor_id) ->
-      window.competitorsOfCompetitor[competitor_id] ||= []
-
-      $.each window.competitors, (index, otherCompetitorId) ->
-        window.competitorsOfCompetitor[otherCompetitorId] ||= []
-
-        if competitor_id != otherCompetitorId && $.inArray(otherCompetitorId, window.competitorsOfCompetitor[competitor_id]) == -1
+  generateMatches: () ->
+    $.each @competitors, (index, competitor_id) =>
+      @competitorsOfCompetitor[competitor_id] ||= []
+
+      $.each @competitors, (index, otherCompetitorId) =>
+        @competitorsOfCompetitor[otherCompetitorId] ||= []
+
+        if competitor_id != otherCompetitorId && $.inArray(otherCompetitorId, @competitorsOfCompetitor[competitor_id]) == -1
           window.matches.push { competitors: [competitor_id, otherCompetitorId] }
-          window.competitorsOfCompetitor[competitor_id].push otherCompetitorId
-          window.competitorsOfCompetitor[otherCompetitorId].push competitor_id
+          @competitorsOfCompetitor[competitor_id].push otherCompetitorId
+          @competitorsOfCompetitor[otherCompetitorId].push competitor_id

-  @nextMatch: () ->
-    window.currentMatch = null
-
-    $.each window.matches, (index, match) ->
+  nextMatch: () ->
+    @currentMatch = null
+
+    $.each window.matches, (index, match) =>
       if match['winner_competitor'] == undefined
-        window.currentMatch = match
-        window.currentMatchIndex = index
+        @currentMatch = match
+        @currentMatchIndex = index

         return

-    if window.currentMatch == null
+    if @currentMatch == null
       alert 'No matches to rate left.'

       return false
@@ -109,16 +115,16 @@
       competitorStrings = []
       i = 0

-      $.each window.currentMatch['competitors'], (index, competitorId) ->
+      $.each @currentMatch['competitors'], (index, competitorId) =>
         competitorDomElement = $('#competitor_' + competitorId)
         checked = ' checked="checked"'
         checked = '' if i == 1
         radioButtons.push ('<input type="radio" ' + checked + ' name="winner" value="' + competitorId + '" style="position:relative; top:-5px "/>')

-        if window.competitiveListOptions['competitor_name_proc'] == undefined || $(competitorDomElement).find('.competitor_name').data('proc-argument') == undefined
+        if @competitiveListOptions['competitor_name_proc'] == undefined || $(competitorDomElement).find('.competitor_name').data('proc-argument') == undefined
           competitorStrings.push $(competitorDomElement).find('.competitor_name').html()
         else
-          competitorStrings.push window.competitiveListOptions['competitor_name_proc']($(competitorDomElement).find('.competitor_name').data('proc-argument'))
+          competitorStrings.push @competitiveListOptions['competitor_name_proc']($(competitorDomElement).find('.competitor_name').data('proc-argument'))

         i += 1

@@ -126,7 +132,7 @@
 <form class="form-inline" style="margin:0px;">

     <button type="button" id="close_bootstrap_modal_button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
-
Appoint Winner (#{window.matchesLeft} matches left)

+
Appoint Winner (#{@matchesLeft} matches left)

@@ -159,106 +165,101 @@

       return true

-  @letWinnerWinMatchesAgainstCompetitorsWhichLoseAgainstLoser: (winnerId, loserId) ->
-    $.each window.matches, (index, match) ->
-      matchOfWinner = $.inArray(winnerId, match['competitors'])
-      return true if matchOfWinner == -1
-
-      matchCompetitorsWhichIncludeLoser = jQuery.map(match['competitors'], (c) ->
-        if $.inArray(c, window.Voluntary.DomManipulation.CompetitiveList.defeatedCompetitorsByCompetitor(loserId)) > -1
+  letWinnerWinMatchesAgainstCompetitorsWhichLoseAgainstLoser: (winnerId, loserId) ->
+    @defeatedCompetitorsByCompetitor[loserId] ||= []
+
+    $.each window.matches, (index, match) =>
+      return true if match['winner_competitor'] == winnerId || $.inArray(winnerId, match['competitors']) == -1
+
+      matchCompetitorsWhichIncludeLoser = jQuery.map(match['competitors'], (c) =>
+        if $.inArray(c, @defeatedCompetitorsByCompetitor[loserId]) > -1
           return c
       )

-      return true if match['winner_competitor'] == winnerId || matchCompetitorsWhichIncludeLoser.length == 0
-
-      otherLoserId = window.Voluntary.DomManipulation.CompetitiveList.otherCompetitorOfMatch(match, winnerId)
-
-      window.matchesWon[winnerId] ||= 0
-      window.matchesWon[winnerId] = window.matchesWon[winnerId] + 1
-
-      unless match['winner_competitor'] == undefined
-        window.Voluntary.DomManipulation.CompetitiveList.changeCompetitorsComparisonResult(winnerId, otherLoserId)
-
-      window.Voluntary.DomManipulation.CompetitiveList.appointWinnerOfMatch(index, winnerId, loserId, match['winner_competitor'] == undefined)
+      return true if matchCompetitorsWhichIncludeLoser.length == 0
+
+      otherLoserId = @otherCompetitorOfMatch(match, winnerId)
+
+      @changeCompetitorsComparisonResult(winnerId, otherLoserId) unless match['winner_competitor'] == undefined
+
+      @appointWinnerOfMatch(index, winnerId, otherLoserId, match['winner_competitor'] == undefined)
       window.matches[index]['winner_competitor'] = winnerId
-      console.log 'auto_winner through @letWinnerWinMatchesAgainstCompetitorsWhichLoseAgainstLoser: ' + JSON.stringify([winnerId, loserId])
       window.matches[index]['auto_winner'] = true

-  @changeCompetitorsComparisonResult: (winnerId, loserId) ->
-    window.matchesWon[loserId] = window.matchesWon[loserId] - 1
-    window.outmatchedCompetitorsByCompetitor[winnerId] ||= []
-    window.outmatchedCompetitorsByCompetitor[winnerId] = window.Voluntary.DomManipulation.CompetitiveList.removeItemFromArray(window.outmatchedCompetitorsByCompetitor[winnerId], loserId)
-    window.defeatedCompetitorsByCompetitor[loserId] = window.Voluntary.DomManipulation.CompetitiveList.removeItemFromArray(window.outmatchedCompetitorsByCompetitor[loserId], winnerId)
-
-  @defeatedCompetitorsByCompetitor: (competitorId) ->
-    window.defeatedCompetitorsByCompetitor[competitorId] ||= []
-
-    return window.defeatedCompetitorsByCompetitor[competitorId]
-
-  @otherCompetitorOfMatch: (match, competitorId) ->
+  changeCompetitorsComparisonResult: (winnerId, loserId) ->
+    @outmatchedCompetitorsByCompetitor[winnerId] ||= []
+    @outmatchedCompetitorsByCompetitor[winnerId] = @removeItemFromArray(@outmatchedCompetitorsByCompetitor[winnerId], loserId)
+    @defeatedCompetitorsByCompetitor[loserId] = @removeItemFromArray(@outmatchedCompetitorsByCompetitor[loserId], winnerId)
+
+  getDefeatedCompetitorsByCompetitor: (competitorId) ->
+    @defeatedCompetitorsByCompetitor[competitorId] ||= []
+
+    return @defeatedCompetitorsByCompetitor[competitorId]
+
+  otherCompetitorOfMatch: (match, competitorId) ->
     otherCompetitors = jQuery.map(match['competitors'], (c) ->
       if c != competitorId
         return c
     )
     return otherCompetitors[0]

-  @appointWinnerOfMatchByInput: () ->
+  appointWinnerOfMatchByInput: () ->
     winnerId = parseInt($("input[name='winner']:checked").val())
-    loserId = window.Voluntary.DomManipulation.CompetitiveList.otherCompetitorOfMatch(window.currentMatch, winnerId)
-
-    window.Voluntary.DomManipulation.CompetitiveList.appointWinnerOfMatch(window.currentMatchIndex, winnerId, loserId, true)
-
-    unless window.Voluntary.DomManipulation.CompetitiveList.nextMatch()
-      window.Voluntary.DomManipulation.CompetitiveList.sortByMostMatchesWon()
+    loserId = @otherCompetitorOfMatch(@currentMatch, winnerId)
+
+    @appointWinnerOfMatch(@currentMatchIndex, winnerId, loserId, true)
+
+    unless @nextMatch()
+      @sortByMostWins()
       $('#bootstrap_modal').modal('hide')

-  @appointWinnerOfMatch: (matchIndex, winnerId, loserId, decrementMatchesLeft) ->
+  appointWinnerOfMatch: (matchIndex, winnerId, loserId, decrementMatchesLeft) ->
     window.matches[matchIndex]['winner_competitor'] = winnerId
-    window.matchesLeft = window.matchesLeft - 1 if decrementMatchesLeft
-
-    window.Voluntary.DomManipulation.CompetitiveList.incrementMatchesWon(winnerId, loserId)
-    window.Voluntary.DomManipulation.CompetitiveList.letWinnerWinMatchesAgainstCompetitorsWhichLoseAgainstLoser(winnerId, loserId)
-    window.Voluntary.DomManipulation.CompetitiveList.letOutMatchedCompetitorsOfWinnerWinAgainstLoser(winnerId, loserId)
-
-  @letOutMatchedCompetitorsOfWinnerWinAgainstLoser: (winnerId, loserId) ->
-    $.each window.Voluntary.DomManipulation.CompetitiveList.outmatchedCompetitorsByCompetitor(winnerId), (index, competitorId) ->
-      window.Voluntary.DomManipulation.CompetitiveList.letCompetitorWinMatchAgainstOtherCompetitor(competitorId, loserId)
-
-  @outmatchedCompetitorsByCompetitor: (competitorId) ->
-    window.outmatchedCompetitorsByCompetitor[competitorId] ||= []
-
-    return window.outmatchedCompetitorsByCompetitor[competitorId]
-
-  @letCompetitorWinMatchAgainstOtherCompetitor: (winnerId, loserId) ->
+    @matchesLeft = @matchesLeft - 1 if decrementMatchesLeft
+
+    @updateDefeatedAndOutmatchedCompetitorsByCompetitor(winnerId, loserId)
+    @letWinnerWinMatchesAgainstCompetitorsWhichLoseAgainstLoser(winnerId, loserId)
+    @letOutMatchedCompetitorsOfWinnerWinAgainstLoser(winnerId, loserId)
+
+  letOutMatchedCompetitorsOfWinnerWinAgainstLoser: (winnerId, loserId) ->
+    @outmatchedCompetitorsByCompetitor[winnerId] ||= []
+
+    $.each @outmatchedCompetitorsByCompetitor[winnerId], (index, competitorId) =>
+      @letCompetitorWinMatchAgainstOtherCompetitor(competitorId, loserId)
+
+    return @outmatchedCompetitorsByCompetitor[competitorId]
+
+  letCompetitorWinMatchAgainstOtherCompetitor: (winnerId, loserId) ->
+    $.each window.matches, (index, match) =>
+      if $.inArray(winnerId, match['competitors']) > -1 && $.inArray(loserId, match['competitors']) > -1 && match['winner_competitor'] != winnerId
+        window.matches[index]['auto_winner'] = true
+        @changeCompetitorsComparisonResult(winnerId, loserId) unless match['winner_competitor']  == undefined
+        @appointWinnerOfMatch(index, winnerId, loserId, match['winner_competitor']  == undefined)
+
+        return false
+
+  updateDefeatedAndOutmatchedCompetitorsByCompetitor: (winnerId, loserId) ->
+    @defeatedCompetitorsByCompetitor[winnerId] ||= []
+    @defeatedCompetitorsByCompetitor[winnerId].push loserId
+
+    @outmatchedCompetitorsByCompetitor[loserId] ||= []
+    @outmatchedCompetitorsByCompetitor[loserId].push winnerId
+
+  cancelTournament: ->
+    @sortByMostWins()
+    $('#bootstrap_modal').modal('hide')
+
+  sortByMostWins: ->
+    winsByCompetitor = {}
+
+    $.each @competitors, (index, competitorId) =>
+      winsByCompetitor[competitorId] = 0
+
     $.each window.matches, (index, match) ->
-      if $.inArray(winnerId, match['competitors']) > -1 && $.inArray(loserId, match['competitors']) > -1 && match['winner_competitor'] != winnerId
-        console.log 'auto_winner through @letCompetitorWinMatchAgainstOtherCompetitor: ' + JSON.stringify([winnerId, loserId])
-        window.matches[index]['auto_winner'] = true
-        window.Voluntary.DomManipulation.CompetitiveList.changeCompetitorsComparisonResult(winnerId, loserId) unless match['winner_competitor']  == undefined
-        window.Voluntary.DomManipulation.CompetitiveList.appointWinnerOfMatch(index, winnerId, loserId, match['winner_competitor']  == undefined)
-
-        return false
-
-  @incrementMatchesWon: (winnerId, loserId) ->
-    window.matchesWon[winnerId] ||= 0
-    window.matchesWon[winnerId] = window.matchesWon[winnerId] + 1
-
-    window.Voluntary.DomManipulation.CompetitiveList.defeatedCompetitorsByCompetitor(winnerId)
-    window.defeatedCompetitorsByCompetitor[winnerId] ||= []
-    window.defeatedCompetitorsByCompetitor[winnerId].push loserId
-
-    window.Voluntary.DomManipulation.CompetitiveList.outmatchedCompetitorsByCompetitor(loserId)
-    window.outmatchedCompetitorsByCompetitor[loserId] ||= []
-    window.outmatchedCompetitorsByCompetitor[loserId].push winnerId
-
-  @cancelTournament: ->
-    window.Voluntary.DomManipulation.CompetitiveList.sortByMostMatchesWon()
-    $('#bootstrap_modal').modal('hide')
-
-  @sortByMostMatchesWon: ->
-    $.each window.competitors, (index, competitorId) ->
-      window.matchesWon[competitorId] ||= 0
-      $('#competitor_' + competitorId).data('wins', window.matchesWon[competitorId])
+      winsByCompetitor[match['winner_competitor']] += 1
+
+    $.each Object.keys(winsByCompetitor), (index, competitorId) ->
+      $('#competitor_' + competitorId).data 'wins', winsByCompetitor[competitorId]

     $wrapper = $('.competitive_list')

@@ -272,8 +273,8 @@
     $.each $('.competitive_list li'), (index, element) ->
       positions[currentPosition] = $(element).data('id')
       $(element).data('position', currentPosition)
-      $(element).find('.competitorPosition').html(currentPosition)
+      $(element).find('.competitor_position').html(currentPosition)
       currentPosition += 1

     data = { _method: 'put', positions: positions, matches: JSON.stringify(window.matches) }
-    $.post $('.competitive_list').data('update-all-positions-path'), data
+    $.post $('.competitive_list').data('update-all-positions-path'), data


there are two CIDs present in the object. Extended formbuilder is using cid set in the model, hence needs get method to retrieve it.

--- coffee/main.coffee
+++ coffee/main.coffee
@@ -982,7 +982,7 @@
         @handleFormUpdate()

       createAndShowEditView: (model) ->
-        $responseFieldEl = @$el.find(".fb-field-wrapper").filter( -> $(@).data('cid') == model.cid )
+        $responseFieldEl = @$el.find(".fb-field-wrapper").filter( -> $(@).data('cid') == model.get('cid'))
         $responseFieldEl.addClass('editing').siblings('.fb-field-wrapper').removeClass('editing')

         if @editView


Changed cursor token method

Changed cursor token method

--- coffee/main.coffee
+++ coffee/main.coffee
@@ -78,15 +78,13 @@
       saved = not err?
       updateTitle()

-cursorToken = '^^^cursor^^^'
 updateView = ->
   cline = editor.getCursor().line
   md = editor.getValue().split '\n'
-  md[cline] += cursorToken
+  md[cline] += ''
   md = md.join '\n'
   v = viewEl
-  #v.innerHTML = markdown.makeHtml(md).replace(cursorToken, '')
-  v.innerHTML = marked(md).replace cursorToken, ''
+  v.innerHTML = marked md
   updateIndex() if state.index
   updateToc() if state.toc
   scrollTop = viewWrapEl.scrollTop
@@ -96,6 +94,7 @@
   cursorHeight = cursorSpan.offsetHeight
   if cursorTop < scrollTop or cursorTop > scrollTop + viewHeight - cursorHeight
     viewWrapEl.scrollTop = cursorTop - viewHeight/2
+
 updateTitle = ->
   document.title = (if saved then '' else '*')+docTitle()


social: code cleanup

social: code cleanup

remove some unused methods

--- workers/social/lib/social/models/account.coffee
+++ workers/social/lib/social/models/account.coffee
@@ -76,8 +76,8 @@
         'fetchMounts','fetchActivityTeasers','fetchRepos','fetchDatabases'
         'fetchMail','fetchNotificationsTimeline','fetchActivities'
         'fetchStorage','count','addTags','fetchLimit', 'fetchLikedContents'
-        'fetchFollowedTopics', 'fetchKiteChannelId', 'setEmailPreferences'
-        'fetchNonces', 'glanceMessages', 'glanceActivities', 'fetchRole'
+        'fetchFollowedTopics', 'setEmailPreferences'
+        'glanceMessages', 'glanceActivities', 'fetchRole'
         'fetchAllKites','flagAccount','unflagAccount','isFollowing'
         'fetchFeedByTitle', 'updateFlags','fetchGroups','fetchGroupRoles',
         'setStaticPageVisibility','addStaticPageType','removeStaticPageType',
@@ -654,30 +654,6 @@
             activity.mark client, 'glanced', -> queue.fin()
           dash queue, callback

-  fetchNonces: secure (client, callback)->
-    {delegate} = client.connection
-    unless @equals delegate
-      callback new KodingError 'Access denied'
-    else
-      client.connection.remote.fetchClientId (clientId)->
-        JSession.one {clientId}, (err, session)->
-          if err
-            callback err
-          else
-            nonces = (hat() for i in [0...10])
-            session.update $addToSet: nonces: $each: nonces, (err)->
-              if err
-                callback err
-              else
-                callback null, nonces
-
-  fetchKiteChannelId: secure (client, kiteName, callback)->
-    {delegate} = client.connection
-    unless delegate instanceof JAccount
-      callback new KodingError 'Access denied'
-    else
-      callback null, "private-#{kiteName}-#{delegate.profile.nickname}"
-
   fetchLikedContents: secure ({connection}, options, selector, callback)->

     {delegate} = connection