Reuse delegated listener in spec reporter

--- spec/atom-reporter.coffee
+++ spec/atom-reporter.coffee
@@ -2,6 +2,8 @@
 _ = require 'underscore-plus'
 grim = require 'grim'
 marked = require 'marked'
+
+listen = require '../src/delegated-listener'

 formatStackTrace = (spec, message='', stackTrace) ->
   return stackTrace unless stackTrace
@@ -27,19 +29,6 @@

   lines = lines.map (line) -> line.trim()
   lines.join('\n').trim()
-
-listen = (element, eventName, selector, handler) ->
-  innerHandler = (event) ->
-    if selector
-      currentTarget = event.target
-      loop
-        if currentTarget.matches and currentTarget.matches(selector)
-          handler({currentTarget: currentTarget, preventDefault: -> event.preventDefault()})
-
-        break if currentTarget is element
-        currentTarget = currentTarget.parentNode
-
-  element.addEventListener(eventName, innerHandler)

 module.exports =
 class AtomReporter


fix(stats): serve stats in non prod

fix(stats): serve stats in non prod

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -261,7 +261,7 @@

 	srcs = []

-	if runStats
+	if not isProd
 		srcs.push src =
 			gulp
 				.src '**', cwd: STATS_DIST_DIRECTORY


redirect to the index page

redirect to the index page

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -185,7 +185,7 @@
     app.listen Config.port
     lr.listen 35729
     setTimeout ->
-        open "http://localhost:" + Config.port + "/styleguide.html"
+        open "http://localhost:" + Config.port
     , 3000

 # Update the livereload server


Use sourcemaps

Use sourcemaps

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -6,35 +6,40 @@
 notify       = require 'gulp-notify'
 plumber      = require 'gulp-plumber'
 rename       = require 'gulp-rename'
+sourcemaps   = require 'gulp-sourcemaps'
 stylus       = require 'gulp-stylus'
 uglify       = require 'gulp-uglify'

 # Stylus
 gulp.task 'stylus', ->
     gulp.src 'resources/stylus/**/*.styl'
-    .pipe plumber
-        errorHandler: notify.onError 'Error: <%= error.message %>'
-    .pipe ignore.exclude '**/_*.styl'
-    .on 'error', gutil.log
-    .pipe stylus()
-    .pipe rename
-        suffix: '.min'
-    .pipe minifycss
-        processImport: yes
-    .pipe gulp.dest 'public/css/dist'
+        .pipe sourcemaps.init()
+        .pipe plumber
+            errorHandler: notify.onError 'Error: <%= error.message %>'
+        .pipe ignore.exclude '**/_*.styl'
+        .on 'error', gutil.log
+        .pipe stylus()
+        .pipe rename
+            suffix: '.min'
+        .pipe minifycss
+            processImport: yes
+        .pipe sourcemaps.write()
+        .pipe gulp.dest 'public/css/dist'

 # Front-end scripts
 gulp.task 'coffee', ->
     gulp.src 'resources/coffee/**/*.coffee'
-    .pipe plumber
-        errorHandler: notify.onError 'Error: <%= error.message %>'
-    .pipe coffee
-        bare: no
-    .on 'error', gutil.log
-    .pipe uglify()
-    .pipe rename
-        suffix: '.min'
-    .pipe gulp.dest 'public/js/dist'
+        .pipe sourcemaps.init()
+        .pipe plumber
+            errorHandler: notify.onError 'Error: <%= error.message %>'
+        .pipe coffee
+            bare: no
+        .on 'error', gutil.log
+        .pipe uglify()
+        .pipe rename
+            suffix: '.min'
+        .pipe sourcemaps.write()
+        .pipe gulp.dest 'public/js/dist'

 # Watch task
 gulp.task 'watch', ->


Add minify css

Add minify css

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -17,12 +17,11 @@
 ngConstant = require 'gulp-ng-constant'
 gulpif = require 'gulp-if'
 htmlreplace = require 'gulp-html-replace'
+minifyCss = require 'gulp-minify-css'
 args = require 'yargs'
-		.alias 'p', 'prod'
-  		.alias 'i', 'int'
-  		.default 'prod', false
-  		.default 'int', true
-  		.argv;
+	.alias 'p', 'prod'
+	.default 'prod', false
+	.argv;

 paths =
 	coffee: "#{outline.src}/**/*.coffee"
@@ -63,6 +62,7 @@
 	gulp.src [paths.sass]
 		.pipe sass(outputStyle: 'compressed')
 		.pipe concat("#{outline.name}.min.css")
+		.pipe gulpif(args.prod, minifyCss())
 		.pipe gulp.dest("#{outline.dist}/css")
 		.pipe reload(stream: true)


chore(gulp): hariko-parser excludes jshint target

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -3,7 +3,12 @@
 gulp.task 'lib', ->
   jshint  = require('gulp-jshint')
   stylish = require('jshint-stylish')
-  gulp.src([ './lib/*.js', './lib/**/*.js' ])
+  gulp.src([
+    './lib/*.js',
+    './lib/**/*.js',
+    '!./lib/hariko-parser/**/*.js',
+    '!./lib/hariko-parser/**/*.js',
+    ])
     .pipe jshint(
     )
     .pipe jshint.reporter(stylish)


Correção na geração dos paths do ngTemplate

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -51,7 +51,7 @@
   gulp.src(sources.html)
   .pipe($.angularTemplatecache(
     "standalone": true
-    "root": '/assets/js'
+    "root": 'assets/js'
   ))
   .pipe(gulp.dest(destinations.js))


Fix gulp typescript-compile path

Fix gulp typescript-compile path

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -13,7 +13,7 @@
 		.pipe gulp.dest './app/lib/web/views/'

 gulp.task 'typescript-compile', ->
-	gulp.src './src/lib/*.ts'
+	gulp.src './src/lib/**.ts'
 		.pipe ts
 			target: 'ES5'
 			removeComments: true
@@ -21,30 +21,6 @@
 			declarationFiles: false
 		.js
 		.pipe gulp.dest './app/lib/'
-	gulp.src './src/lib/model/*.ts'
-		.pipe ts
-			target: 'ES5'
-			removeComments: true
-			noImplicitAny: true
-			declarationFiles: false
-		.js
-		.pipe gulp.dest './app/lib/model/'
-	gulp.src './src/lib/web/*.ts'
-		.pipe ts
-			target: 'ES5'
-			removeComments: true
-			noImplicitAny: true
-			declarationFiles: false
-		.js
-		.pipe gulp.dest './app/lib/web/'
-	gulp.src './src/lib/web/models/*.ts'
-		.pipe ts
-			target: 'ES5'
-			removeComments: true
-			noImplicitAny: true
-			declarationFiles: false
-		.js
-		.pipe gulp.dest './app/lib/web/models/'

 gulp.task 'watch', ['build'], ->
 	gulp.watch './src/lib/*.ts', ['typescript-compile']


Cleanup

Cleanup

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -10,9 +10,6 @@
 gulp = require('gulp-task-master')(taskMasterOptions)

-#gulp.task "watch",  ['compile-lib.watch','compile-bin.watch']
-#gulp.task "bot", ['compile-lib.watch','compile-bin.watch']

-
-#gulp.task "default", ['compile-lib','compile-bin']
+gulp.task "default", ['compile']


test with empty array

test with empty array

--- spec/specs/combine.coffee
+++ spec/specs/combine.coffee
@@ -162,6 +162,11 @@
         Bacon.combineWith(f, [Bacon.constant(0), Bacon.constant(1)])
       [1]
     )
+  describe "works with empty array", ->
+    expectPropertyEvents(
+      -> Bacon.combineWith((-> 1), [])
+      [1]
+    )
   it "toString", ->
     expect(Bacon.combineWith((->), Bacon.never()).toString()).to.equal("Bacon.combineWith(function,Bacon.never())")


Disallow unloading of OpServ

Disallow unloading of OpServ

--- handlers.coffee
+++ handlers.coffee
@@ -48,6 +48,11 @@
 			callback "compile" if callback?

 unloadHandler = (name, callback) ->
+	if name is 'opserv'
+		winston.warn "Trying to unload opserv"
+		callback "permissionDenied" if callback?
+		return
+
 	winston.debug 'Unloading handler:', name
 	unless loadedHandlers[name]?
 		winston.warn "Trying to unload unloaded handler", name


add specs for change operation

add specs for change operation

Mostly cribbed from the delete ones, except skipping the `dd` one (for
deleting/changing an entire line).

The main difference is making sure the editor is in insert mode (and
not in command mode) after the action is performed.

--- spec/vim-mode-spec.coffee
+++ spec/vim-mode-spec.coffee
@@ -200,6 +200,74 @@

           expect(editor.getText()).toBe "ee four"
           expect(editor.getCursorScreenPosition()).toEqual([0,0])
+
+    describe "the c keybinding", ->
+      describe "when followed by an h", ->
+        it "deletes the previous letter on the current line and enters insert mode", ->
+          editor.setText("abcd\n01234")
+          editor.setCursorScreenPosition([1,1])
+
+          keydown('c', element: editor[0])
+          keydown('h', element: editor[0])
+
+          expect(editor.getText()).toBe "abcd\n1234"
+          expect(editor.getCursorScreenPosition()).toEqual([1,0])
+          expect(editor).not.toHaveClass 'command-mode'
+          expect(editor).toHaveClass 'insert-mode'
+
+      describe "when followed by a w", ->
+        it "deletes to the beginning of the next word and enters insert mode", ->
+          editor.setText("abcd efg")
+          editor.setCursorScreenPosition([0,2])
+
+          keydown('c', element: editor[0])
+          keydown('w', element: editor[0])
+
+          expect(editor.getText()).toBe "abefg"
+          expect(editor.getCursorScreenPosition()).toEqual([0,2])
+          expect(editor).not.toHaveClass 'command-mode'
+          expect(editor).toHaveClass 'insert-mode'
+
+          editor.trigger keydownEvent('escape')
+
+          editor.setText("one two three four")
+          editor.setCursorScreenPosition([0,0])
+
+          keydown('c', element: editor[0])
+          keydown('3', element: editor[0])
+          keydown('w', element: editor[0])
+
+          expect(editor.getText()).toBe "four"
+          expect(editor.getCursorScreenPosition()).toEqual([0,0])
+          expect(editor).not.toHaveClass 'command-mode'
+          expect(editor).toHaveClass 'insert-mode'
+
+      describe "when followed by a b", ->
+        it "deletes to the beginning of the previous word and enters insert mode", ->
+          editor.setText("abcd efg")
+          editor.setCursorScreenPosition([0,2])
+
+          keydown('c', element: editor[0])
+          keydown('b', element: editor[0])
+
+          expect(editor.getText()).toBe "cd efg"
+          expect(editor.getCursorScreenPosition()).toEqual([0,0])
+          expect(editor).not.toHaveClass 'command-mode'
+          expect(editor).toHaveClass 'insert-mode'
+
+          editor.trigger keydownEvent('escape')
+
+          editor.setText("one two three four")
+          editor.setCursorScreenPosition([0,11])
+
+          keydown('c', element: editor[0])
+          keydown('3', element: editor[0])
+          keydown('b', element: editor[0])
+
+          expect(editor.getText()).toBe "ee four"
+          expect(editor.getCursorScreenPosition()).toEqual([0,0])
+          expect(editor).not.toHaveClass 'command-mode'
+          expect(editor).toHaveClass 'insert-mode'

     describe "the y keybinding", ->
       beforeEach ->


Refactor some ConflictMarker specs.

Refactor some ConflictMarker specs.

--- spec/conflict-marker-spec.coffee
+++ spec/conflict-marker-spec.coffee
@@ -2,47 +2,43 @@
 util = require './util'

 describe 'ConflictMarker', ->
-  [editorView] = []
+  [editorView, m] = []

   beforeEach ->
     editorView = util.openPath("triple-2way-diff.txt")
     editorView.getFirstVisibleScreenRow = -> 0
     editorView.getLastVisibleScreenRow = -> 999

+    m = new ConflictMarker(editorView)
+
   it 'attaches two SideViews and a NavigationView for each conflict', ->
-    new ConflictMarker(editorView)
     expect(editorView.find('.side').length).toBe(6)
     expect(editorView.find('.navigation').length).toBe(3)

   it 'adds the conflicted class', ->
-    new ConflictMarker(editorView)
     expect(editorView.hasClass 'conflicted').toBe(true)

   it 'removes any old classes', ->
     line = editorView.renderedLines.eq(2)
     line.addClass "ours"
-    new ConflictMarker(editorView)
+    m.remark()
     expect(line.hasClass 'ours').toBe(false)

   it 'locates the correct lines', ->
-    m = new ConflictMarker(editorView)
     lines = m.linesForMarker m.conflicts[1].ours.marker
     expect(lines.text()).toBe("My middle changes")

   it 'applies the "ours" class to our sides of conflicts', ->
-    m = new ConflictMarker(editorView)
     lines = m.linesForMarker m.conflicts[0].ours.marker
     expect(lines.hasClass 'conflict-line').toBe(true)
     expect(lines.hasClass 'ours').toBe(true)

   it 'applies the "theirs" class to their sides of conflicts', ->
-    m = new ConflictMarker(editorView)
     lines = m.linesForMarker m.conflicts[0].theirs.marker
     expect(lines.hasClass 'conflict-line').toBe(true)
     expect(lines.hasClass 'theirs').toBe(true)

   it 'applies the "dirty" class to modified sides', ->
-    m = new ConflictMarker(editorView)
     editor = editorView.getEditor()
     editor.setCursorBufferPosition [14, 0]
     editor.insertText "Make conflict 1 dirty"
@@ -55,7 +51,6 @@
     expect(lines.hasClass 'ours').toBe(false)

   it 'applies the "resolved" class to resolved conflicts', ->
-    m = new ConflictMarker(editorView)
     m.conflicts[1].ours.resolve()
     m.remark()
     lines = m.linesForMarker m.conflicts[1].ours.marker
@@ -63,8 +58,6 @@
     expect(lines.hasClass 'resolved').toBe(true)

   it 'broadcasts the "merge-conflicts:resolved" event', ->
-    m = new ConflictMarker(editorView)
-
     event = null
     atom.on 'merge-conflicts:resolved', (e) -> event = e
     m.conflicts[2].theirs.resolve()


Might work by changing things around

Might work by changing things around

--- app/assets/javascripts/incident_reports/edit.coffee
+++ app/assets/javascripts/incident_reports/edit.coffee
@@ -35,7 +35,9 @@
   addFields '.pax-fields'

 deleteFields = (fieldsSelector) ->
-  $(fieldsSelector).last().remove()
+  fields = $(fieldsSelector).last()
+  fields.find('input').remove()
+  fields.remove()

 deleteWitnessFields = (event) ->
   event.preventDefault()


allow custom wrapper parameter

allow custom wrapper parameter

--- app/assets/javascripts/lib/models/chart_list.coffee
+++ app/assets/javascripts/lib/models/chart_list.coffee
@@ -29,6 +29,8 @@
   #                           needed on the initial render, where we want to
   #                           plot the charts and preserve the locks
   #             wait        - don't fire the API request immediately
+  #             wrapper     - selector for the wrapper that will contain the
+  #                           chart holder
   #
   # Returns the newly created chart object or false if something went wrong
   load: (chart_id, holder_id = null, options = {}) =>
@@ -143,22 +145,30 @@
   # holder_id
   #
   # holder_id - id of the container to add. If null it will be generated
-  # header    - boolean to show or hide the header bar. Usually passed by the
-  #             load() method above. Dashboard popups set it to false, regular
-  #             charts to true
+  # options   - hash of optional parameters
+  #             header    - boolean to show or hide the header bar. Usually
+  #                         passed by the load() method above. Dashboard
+  #                         popups set it to false, regular charts to true
+  #             wrapper   - the DOM element where the container will be
+  #                         appended. The default is '#charts_wrapper'
   #
   add_container_if_needed: (holder_id = null, options = {}) =>
     if !holder_id
       timestamp = (new Date()).getTime()
       holder_id = "holder_#{timestamp}"

-    if @container.find("##{holder_id}").length == 0
+    $container = if options.wrapper
+      $(options.wrapper)
+    else
+      @container
+
+    if $container.find("##{holder_id}").length == 0
       new_chart = @template(
         title: 'foo'
         chart_id: 0
         holder_id: holder_id
         header: options.header)
-      @container.append new_chart
+      $container.append new_chart
     holder_id

   # This stuff could be moved to the view, but a document-scoped event binding


Fixed issue with incorrect line being highlighted if line is in discussion view

--- app/assets/javascripts/merge_request_tabs.js.coffee
+++ app/assets/javascripts/merge_request_tabs.js.coffee
@@ -176,12 +176,12 @@

     if locationHash isnt ''
       hashClassString = ".#{locationHash.replace('#', '')}"
-      $diffLine = $(locationHash)
-
-      if $diffLine.is ':not(tr)'
-        $diffLine = $("td#{locationHash}, td#{hashClassString}")
+      $diffLine = $("#{locationHash}:not(.match)", $('#diffs'))
+
+      if not $diffLine.is 'tr'
+        $diffLine = $('#diffs').find("td#{locationHash}, td#{hashClassString}")
       else
-        $diffLine = $('td', $diffLine)
+        $diffLine = $diffLine.find('td')

       if $diffLine.length
         $diffLine.addClass 'hll'


column typeをEnterで決定した時の動作を修正

column typeをEnterで決定した時の動作を修正

--- app/assets/javascripts/ponytail/views/column.coffee
+++ app/assets/javascripts/ponytail/views/column.coffee
@@ -32,8 +32,9 @@
       @.blurColumnType()

   blurColumnType: ->
-    @$(".column_type span").toggle()
-    @$(".column_type select").toggle()
+    if @$(".column_type select").is(":visible")
+      @$(".column_type span").toggle()
+      @$(".column_type select").toggle()

   clickColumnName: ->
     if @$(".column_name span").is(":visible")


Better button sizing for small divs.

Better button sizing for small divs.

--- app/assets/javascripts/roofpig/DomHandler.js.coffee
+++ app/assets/javascripts/roofpig/DomHandler.js.coffee
@@ -63,4 +63,4 @@

   _scale: (button_area_element) ->
     @button_area.append(button_area_element)
-    button_area_element.height(40 * @scale).width(60 * @scale).css("font-size", 24 * @scale)+    button_area_element.height(40 * @scale).width(72 * @scale - 12).css("font-size", 32 * @scale)


add comment

add comment

--- app/assets/javascripts/views/current_tags.js.coffee
+++ app/assets/javascripts/views/current_tags.js.coffee
@@ -10,6 +10,8 @@
       false

+  # TODO Move the following two to a more prominent place:
+  #
   tagList: (->
     users = @get('allUsers') || []
     @extractTagsFrom(users).sort()


Put all extra content into last cell

Put all extra content into last cell

--- lib/table-formatter.coffee
+++ lib/table-formatter.coffee
@@ -102,6 +102,8 @@
         for line in lines
             line = line.trim().replace(/(^\||\|$)/g,"")
             cells = line.split('|')
+            #put all extra content into last cell
+            cells[columns-1]=cells.slice(columns-1).join('|')
             linecontent = ( ' '.repeat(@spacePadding) + x.trim() + ' '.repeat(@spacePadding) for x in cells )
             content.push(linecontent)


syntax typography

syntax typography

--- hexaflip.coffee
+++ hexaflip.coffee
@@ -4,8 +4,8 @@
 # http://oxism.com
 # Copyright 2013, MIT License

-baseName = 'hexaFlip'
-className = baseName[0].toUpperCase() + baseName[1...]
+baseName   = 'hexaFlip'
+className  = baseName[0].toUpperCase() + baseName[1...]
 prefixList = ['webkit', 'Moz', 'O', 'ms']

 prefixProp = (prop) ->
@@ -19,12 +19,12 @@
 css[prop.toLowerCase()] = prefixProp prop for prop in ['Transform', 'Perspective']

 defaults =
-  size: 200
-  margin: 10
-  fontSize: 132
-  perspective: 1000
+  size:             200
+  margin:           10
+  fontSize:         132
+  perspective:      1000
   touchSensitivity: 1
-  horizontalFlip: false
+  horizontalFlip:   false

 cssClass = baseName.toLowerCase()
 faceNames = ['front', 'bottom', 'back', 'top', 'left', 'right']
@@ -45,12 +45,12 @@
         minute:   (i + '0' for i in [0..5])
         meridian: ['am', 'pm']

-    setsKeys = Object.keys @sets
-    setsLength = setsKeys.length
+    setsKeys     = Object.keys @sets
+    setsLength   = setsKeys.length
     cubeFragment = document.createDocumentFragment()
     i = z = 0
     midPoint = setsLength / 2 + 1
-    @cubes = {}
+    @cubes   = {}
     for key, set of @sets
       cube = @cubes[key] = @_createCube key
       if ++i < midPoint
@@ -67,7 +67,7 @@

     @el.classList.add cssClass
     @el.style.height = @size + 'px'
-    @el.style.width = ((@size + @margin * 2) * setsLength) - @margin * 2 + 'px'
+    @el.style.width  = ((@size + @margin * 2) * setsLength) - @margin * 2 + 'px'
     @el.style[css.perspective] = @perspective + 'px'
     @el.appendChild cubeFragment
     @eProp = if @horizontalFlip then 'pageX' else 'pageY'
@@ -93,10 +93,10 @@
       el:     document.createElement 'div'
       holder: document.createElement 'div'

-    cube.el.className = "#{ cssClass }-cube #{ cssClass }-cube-#{ set }"
+    cube.el.className    = "#{ cssClass }-cube #{ cssClass }-cube-#{ set }"
     cube.el.style.margin = "0 #{ @margin }px"
-    cube.el.style.width = cube.el.style.height =
-      cube.holder.style.width = cube.holder.style.height = @size + 'px'
+    cube.el.style.width  = cube.el.style.height = \
+    cube.holder.style.width = cube.holder.style.height = @size + 'px'
     cube.holder.style[css.transform] = @_getTransform 0
     sideProto = document.createElement 'div'
     sideProto.classList.add cssClass + '-side'
@@ -150,7 +150,7 @@
     return unless el and content
     if typeof content is 'object'
       {style, value} = content
-      el.style[key] = val for key, val of style
+      el.style[key]  = val for key, val of style
     else
       value = content

@@ -183,12 +183,12 @@
         else
           faceOffset = 4 + offset

-    setOffset %= setLength if setOffset >= setLength
+    setOffset  %= setLength if setOffset >= setLength
     faceOffset %= 4 if faceOffset >= 4
-    topAdj = faceOffset - 1
-    bottomAdj = faceOffset + 1
-    topAdj = 3 if topAdj is -1
-    bottomAdj = 0 if bottomAdj is 4
+    topAdj      = faceOffset - 1
+    bottomAdj   = faceOffset + 1
+    topAdj      = 3 if topAdj is -1
+    bottomAdj   = 0 if bottomAdj is 4
     @_setContent cube[faceSequence[topAdj]], set[setOffset - 1] or set[setLength - 1]
     @_setContent cube[faceSequence[bottomAdj]], set[setOffset + 1] or set[0]

@@ -243,7 +243,7 @@
     for key, value of settings
       continue unless @sets[key] and !@cubes[key].touchStarted
       value = value.toString()
-      cube = @cubes[key]
+      cube  = @cubes[key]
       index = @sets[key].indexOf value
       cube.delta = cube.last = 90 * index
       @_setSides cube
@@ -253,9 +253,9 @@

   getValue: ->
     for set, cube of @cubes
-      set = @sets[set]
+      set       = @sets[set]
       setLength = set.length
-      offset = cube.last / 90
+      offset    = cube.last / 90
       if offset < 0
         if -offset > setLength
           offset = setLength - -offset % setLength


Refactor chance; mutates var!

Refactor chance; mutates var!

--- server/bw/data/moves.coffee
+++ server/bw/data/moves.coffee
@@ -59,8 +59,8 @@
     @afterSuccessfulHit = (battle, user, target, damage) ->
       oldFunc.call(this, battle, user, target, damage)
       return  if target.has(Attachment.Substitute)
-      chance *= 2  if user.hasAbility("Serene Grace")
-      return  if battle.rng.next("secondary effect") >= chance
+      multiplier = (if user.hasAbility("Serene Grace") then 2 else 1)
+      return  if battle.rng.next("secondary effect") >= chance * multiplier

       target.attach(Klass, options)

@@ -70,8 +70,8 @@
     @afterSuccessfulHit = (battle, user, target, damage) ->
       oldFunc.call(this, battle, user, target, damage)
       return  if target.has(Attachment.Substitute)
-      chance *= 2  if user.hasAbility("Serene Grace")
-      return  if battle.rng.next("secondary status") >= chance
+      multiplier = (if user.hasAbility("Serene Grace") then 2 else 1)
+      return  if battle.rng.next("secondary status") >= chance * multiplier

       target.attach(status)

@@ -79,11 +79,11 @@
 extendWithFangEffect = (name, chance, status, options) ->
   extendMove name, ->
     @afterSuccessfulHit = (battle, user, target) ->
-      chance *= 2  if user.hasAbility("Serene Grace")
-      if battle.rng.next("fang status") < chance
+      multiplier = (if user.hasAbility("Serene Grace") then 2 else 1)
+      if battle.rng.next("fang status") < chance * multiplier
         target.attach(status)

-      if battle.rng.next("fang flinch") < chance
+      if battle.rng.next("fang flinch") < chance * multiplier
         target.attach(Attachment.Flinch)

 extendWithDrain = (name, drainPercent=.5) ->


Default to 80 when editor.preferredLineLength <= 0

Previously any non-null value would be used as the target
column in the wrap guide and autoflow packages when really
80 should have been used if the value was non-postive.

Now config.getPositiveInt() is called with a default value
of 80 if the current value isn't already positive.

--- lib/wrap-guide-view.coffee
+++ lib/wrap-guide-view.coffee
@@ -19,7 +19,7 @@
     @subscribe $(window), 'resize', => @updateGuide()

   getDefaultColumn: ->
-    config.get('editor.preferredLineLength') ? 80
+    config.getPositiveInt('editor.preferredLineLength', 80)

   getGuideColumn: (path) ->
     customColumns = config.get('wrapGuide.columns')


Add linebreak for Directory::create return val

`Returns` must be separated by a blank line in order to be parsed
correctly for the generated documentation.

--- src/directory.coffee
+++ src/directory.coffee
@@ -43,7 +43,8 @@
   # Public: Creates the directory on disk that corresponds to `::getPath()` if
   # no such directory already exists.
   #
-  # * `mode` Optional {Number} that defaults to `0777`.
+  # * `mode` (optional) {Number} that defaults to `0777`.
+  #
   # Returns a {Promise} that resolves once the directory is created on disk. It
   # resolves to a boolean value that is true if the directory was created or
   # false if it already existed.


Handle browser window config

Handle browser window config

--- lib/models/browser-window-wrapper.coffee
+++ lib/models/browser-window-wrapper.coffee
@@ -8,12 +8,15 @@
     options.show ?= false
     options.width ?= 400
     options.height ?= 600
+    options.skipTaskbar ?= true
+    options.menuBarVisible ?= false

     @win = new BrowserWindow(options)
     @webContents = @win.webContents
+    forceBrowserWindowOptions(@win, options)

     @handleEvents()
-    @win.loadUrl(url)
+    @win.loadUrl(url) # TODO: handle failed load

   handleEvents: =>
     @webContents.on 'did-finish-load', =>
@@ -24,3 +27,11 @@
         e.preventDefault()
         @win.destroy()
         shell.openExternal(url)
+
+  forceBrowserWindowConfigurations: (win, options) ->
+    # these options fail as arguments to the BrowserWindor constructor
+    {skipTaskbar, menuBarVisible, title} = options
+
+    win.setTitle(title) if title?
+    win.setSkipTaskbar(skipTaskbar)
+    win.setMenuBarVisibility(menuBarVisible)


Stopped language-excluded docs from showing up undocumented in the 'this' area of the spell palette.

--- app/views/play/level/tome/spell_palette_view.coffee
+++ app/views/play/level/tome/spell_palette_view.coffee
@@ -55,9 +55,12 @@
   createPalette: ->
     lcs = @supermodel.getModels LevelComponent
     allDocs = {}
+    excludedDocs = {}
     for lc in lcs
       for doc in (lc.get('propertyDocumentation') ? [])
-        continue if doc.codeLanguages and not (@options.language in doc.codeLanguages)
+        if doc.codeLanguages and not (@options.language in doc.codeLanguages)
+          excludedDocs[doc.name] = doc
+          continue
         allDocs['__' + doc.name] ?= []
         allDocs['__' + doc.name].push doc
         if doc.type is 'snippet' then doc.owner = 'snippets'
@@ -100,9 +103,11 @@
         doc = _.find (allDocs['__' + prop] ? []), (doc) ->
           return true if doc.owner is owner
           return (owner is 'this' or owner is 'more') and (not doc.owner? or doc.owner is 'this')
-        console.log 'could not find doc for', prop, 'from', allDocs['__' + prop], 'for', owner, 'of', propGroups unless doc
-        doc ?= prop
-        @entries.push @addEntry(doc, shortenize, tabbify, owner is 'snippets')
+        if not doc and not excludedDocs[prop]
+          console.log 'could not find doc for', prop, 'from', allDocs['__' + prop], 'for', owner, 'of', propGroups unless doc
+          doc ?= prop
+        if doc
+          @entries.push @addEntry(doc, shortenize, tabbify, owner is 'snippets')
     groupForEntry = (entry) ->
       return 'more' if entry.doc.owner is 'this' and entry.doc.name in (propGroups.more ? [])
       entry.doc.owner


Processing Instructions Modal

Processing Instructions Modal

--- src/scripts/modules/media/body/body.coffee
+++ src/scripts/modules/media/body/body.coffee
@@ -186,6 +186,7 @@

     checkKeySequence: (e) ->
       key[e.keyCode] = true
+
       if @model.isDraft()
         #ctrl+alt+shift+p+i
         if key[16] and key[17] and key[18] and key[73] and key[80]


less code

less code

--- src/dt-jquery.coffee
+++ src/dt-jquery.coffee
@@ -110,18 +110,17 @@
             parent = newtag.parent
             $new = newtag._jquery ? newtag
             $old = oldtag._jquery ? oldtag
+            $par = parent._jquery ? parent

             if $new.length is 0
-                newtag._jquery = $new = @$('<spaceholder>', parent._jquery)
+                newtag._jquery = $new = @$('<spaceholder>', $par)
                 newtag._jquery_wrapped = yes
-                if newtag is newtag.builder
-                    $fyBuilder(newtag) # includes defineJQueryAPI
-                else
-                    defineJQueryAPI(newtag)
+                defineJQueryAPI(newtag) unless newtag is newtag.builder

             if parent is parent.builder
                 $par.splice($par.index($old), $old.length, $new...)
                 $fyBuilder(parent)
+
             if $old.parent().length > 0
                 $old.replaceWith($new)
             # replaceWith isnt inplace


Fix that backspacing over a character and then backspacing again to select an attachment would cause an error

--- src/trix/controllers/editor_controller.coffee
+++ src/trix/controllers/editor_controller.coffee
@@ -5,8 +5,6 @@
 #= require trix/models/selection_manager
 #= require trix/models/editor

-{defer} = Trix
-
 class Trix.EditorController extends Trix.Controller
   constructor: (@config) ->
     {@documentElement, @toolbarController, @document, @delegate} = @config
@@ -80,7 +78,7 @@
   compositionDidStartEditingAttachment: (attachment) ->
     @attachmentLocationRange = @document.getLocationRangeOfAttachment(attachment)
     @documentController.installAttachmentEditorForAttachment(attachment)
-    defer => @selectionManager.setLocationRange(@attachmentLocationRange)
+    @selectionManager.setLocationRange(@attachmentLocationRange)

   compositionDidStopEditingAttachment: (attachment) ->
     @documentController.uninstallAttachmentEditor()


trying to impl combineAsArray in terms of Bacon.when

--- src/Bacon.coffee
+++ src/Bacon.coffee
@@ -156,37 +156,9 @@
   for stream, index in streams
     streams[index] = Bacon.constant(stream) if not (stream instanceof Observable)
   if streams.length
-    values = (None for s in streams)
-    new Property (sink) =>
-      ends = (false for s in streams)
-      initialSent = false
-      combiningSink = (index) => (unsubAll) ->
-        streams[index].subscribeInternal (event) =>
-          if (event.isEnd())
-            ends[index] = true
-            if _.all(ends)
-              reply = sink end()
-              unsubAll() if reply == Bacon.noMore
-            Bacon.noMore
-          else if event.isError()
-            reply = sink event
-            unsubAll() if reply == Bacon.noMore
-            reply
-          else
-            values[index] = event.value
-            if _.all(values, ((x) -> x != None))
-              if initialSent and event.isInitial()
-                # don't send duplicate Initial
-                Bacon.more
-              else
-                initialSent = true
-                valueArrayF = -> (x() for x in values)
-                reply = sink(event.apply(valueArrayF))
-                unsubAll() if reply == Bacon.noMore
-                reply
-            else
-              Bacon.more
-      compositeUnsubscribe (combiningSink index for s, index in streams )...
+    sources = for s in streams
+      new Source(s, true, false, s.subscribeInternal)
+    Bacon.when(sources, Array).toProperty()
   else
     Bacon.constant([])

@@ -917,24 +889,30 @@
       sink? end()

 class Source
-  constructor: (s) ->
+  constructor: (s, @sync, consume, @subscribe) ->
     queue = []
     isEnded = false
-    @subscribe = s.subscribe
+    @subscribe = s.subscribe if not @subscribe?
     @markEnded = -> isEnded = true
     @ended = -> isEnded
-    if s instanceof Property
+    if consume
+      @consume = () -> queue.shift()
+      @push  = (x) -> queue.push(x)
+      @mayHave = (c) -> !isEnded || queue.length >= c
+      @hasAtLeast = (c) -> queue.length >= c
+    else
       @consume = () -> queue[0]
       @push  = (x) -> queue = [x]
       @mayHave = -> true
       @hasAtLeast = (c) -> queue.length
-      @sync = false
-    else
-      @consume = () -> queue.shift()
-      @push  = (x) -> queue.push(x)
-      @mayHave = (c) -> !isEnded || queue.length >= c
-      @hasAtLeast = (c) -> queue.length >= c
-      @sync = true
+
+Source.fromObservable = (s) ->
+  if s instanceof Source
+    s
+  else if s instanceof Property
+    new Source(s, false, false)
+  else
+    new Source(s, true, true)

 Bacon.when = (patterns...) ->
     return Bacon.never() if patterns.length == 0
@@ -959,7 +937,7 @@
        pats.push pat
        i = i + 2

-    sources = _.map ((s) -> new Source(s)), sources
+    sources = _.map ((s) -> Source.fromObservable(s)), sources

     new EventStream (sink) ->
       match = (p) ->


Remove console.log()s

Remove console.log()s

--- www/js/views/checkins.coffee
+++ www/js/views/checkins.coffee
@@ -89,8 +89,6 @@
       $(@$el).html(html)

       if @position
-        console.log @venues
-
         self = this

         $('body').addClass 'show-map'
@@ -113,12 +111,10 @@
           bounds = new L.Bounds()

           # Add the top five venues to the map.
-          _.first(@venues, 5).forEach (v) ->
+          _.first(@venues, 4).forEach (v) ->
             L.marker([v.location.lat, v.location.lng]).addTo(self.map)
             bounds.extend [v.location.lat, v.location.lng]
-            console.log v.location.lat, v.location.lng, v.id, v.name

-          console.log bounds
           latLngBounds = new L.LatLngBounds([
             [bounds.min.x, bounds.min.y],
             [bounds.max.x, bounds.max.y]


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/expirable.coffee
+++ src/expirable.coffee
@@ -8,7 +8,6 @@
   self.bind "update", ->
     if I.fadeOut
       I.alpha = 5
-        ;

     if I.duration != -1 && I.age >= I.duration
       I.active = false


Renamed an argument name of setImage

Renamed an argument name of setImage

--- src/Scene.coffee
+++ src/Scene.coffee
@@ -82,19 +82,19 @@

   getImage: -> @_image

-  setImage: (image, callback = null) ->
-    @_image = image
+  setImage: (src, callback = null) ->
+    @_image = src

-    unless image?
+    unless src?
       @style.backgroundColor = null
       @style.backgroundImage = null
-    else if image.charAt(0) is '#'
-      @style.backgroundColor = image
+    else if src.charAt(0) is '#'
+      @style.backgroundColor = src
       @style.backgroundImage = null
     else
       @style.backgroundColor = null
-      @style.backgroundImage = "url(#{image})"
-      DivSugar.getImageSize image, callback if callback?
+      @style.backgroundImage = "url(#{src})"
+      DivSugar.getImageSize src, callback if callback?

     return @


ActivitySidebar: Select machine and workspace.

--- client/Social/Activity/sidebar/activitysidebar.coffee
+++ client/Social/Activity/sidebar/activitysidebar.coffee
@@ -602,8 +602,10 @@

   selectWorkspace: (data) ->

-    box = @getMachineBoxByMachineUId data.machine.uid
-    box?.selectWorkspace data.workspace
+    { machine, workspace } = data
+
+    for machineList in @machineLists
+      machineList.selectMachineAndWorkspace machine.uid, workspace.slug

     # data = @latestWorkspaceData or {}  unless data
     # { workspace, machine } = data


Activity: refactored some itemsOrdered props to get rid of deprecated notices

--- client/Social/Activity/sidebar/activitysidebar.coffee
+++ client/Social/Activity/sidebar/activitysidebar.coffee
@@ -104,7 +104,7 @@
     candidateItems = []
     for own name, {listController} of @sections

-      for item in listController.itemsOrdered
+      for item in listController.getListItems()
         data = item.getData()
         if data.typeConstant is type and (data.id is slug or data.name is slug or data.slug is slug)
           candidateItems.push item
@@ -141,7 +141,7 @@
     itemWeWant = null
     for own name, section of @sections

-      section.listController.itemsOrdered.forEach (item)->
+      section.listController.getListItems().forEach (item)->
         if item.typeConstant is typeConstant
           slugProp = slugProps[item.bongo_.constructorName]
           itemWeWant = item[slugProp] is slug


Fixed sidebar resize handle issue.

Fixed sidebar resize handle issue.

--- client/landing/app/MainApp/sidebar/sidebarview.coffee
+++ client/landing/app/MainApp/sidebar/sidebarview.coffee
@@ -173,7 +173,9 @@
     @finderResizeHandle.on "DragInAction", (x, y)=>
       @finderResizeHandle._dragged = yes
       newFpWidth = @_fpWidth + x
-      return if newFpWidth < 13
+      if newFpWidth < 13
+        @finderResizeHandle.dragIsAllowed = no
+        return no
       cp.$().css left : cp._left + x, width : cp._width - x
       @finderResizeHandle.$().css left: ''
       $fp.css "width", newFpWidth


Update to only load data when needed

Update to only load data when needed

--- client/lanes/components/select-field/SelectField.cjsx
+++ client/lanes/components/select-field/SelectField.cjsx
@@ -1,25 +1,32 @@
 class Lanes.Components.SelectField extends Lanes.React.Component
     mixins: [ Lanes.Components.Form.FieldMixin ]
-
     getDefaultProps: ->
-        labelField: 'name', idField: 'id'
+        labelField: 'name', idField: 'id', displayLimit: 30

     propTypes:
         collection: Lanes.PropTypes.Collection
         labelField: React.PropTypes.string
         getSelection: React.PropTypes.func
         setSelection: React.PropTypes.func
+        displayLimit: React.PropTypes.number

     dataObjects:
         collection: ->
             @props.collection || (
-                @props.model?.associations.collectionFor(@props.name).fetch()
+                @props.model?.associations.collectionFor(@props.name)
             )

-    componentWillMount: ->
-        @collection.ensureLoaded()
+    onChange: (selection) ->
+        return unless  _.isString(selection)
+        options = { limit: @props.displayLimit, order: { "#{@props.labelField}": 'desc' } }
+        unless _.isEmpty(selection)
+            options.query = {
+                "#{@props.labelField}": { op: 'like', value: selection }
+            }

-    onChange: (selections) ->
+        @collection.fetch(options)
+
+    onSelect: (selections) ->
         selections = [selections] unless _.isArray(selections)
         records = _.map selections, (selection) =>
             @collection.get(selection.id)
@@ -30,24 +37,36 @@
             @model.set(@props.name, value)
         true

+    getCurrentModel: ->
+        @model.associations.getModelFromCollection(@model, @props.name, @collection)
+
     getCurrentSelection: ->
         return @props.getSelection(@model) if @props.getSelection
-        pk = @model.associations.pk(@props.name)
-        selected = @collection.get( @model[pk] )
-        return {} unless selected
-        label = selected[@props.labelField]
-        id = selected[@props.idField]
-        label = String(label) if _.isObject(label)
-        {id, label}
+
+        selected = @getCurrentModel()
+
+        if selected
+            {id: selected[@props.idField], label: selected[@props.labelField]}
+        else
+            {id: null, label: ''}
+

     renderDisplayValue: ->
-        {@getCurrentSelection().label}
+        {@getCurrentSelection()?.label}

     _getChoices: ->
-        if _.isFunction(@getChoices) then @getChoices() else
-            labelField = @props.labelField
-            @collection.map (model) ->
-                {id: model.id, label: _.result(model, labelField)}
+        if @state.isOpen
+            if _.isFunction(@getChoices) then @getChoices() else
+                labelField = @props.labelField
+                @collection.map (model) ->
+                    {id: model.id, label: _.result(model, labelField)}
+        else
+            selection = @getCurrentSelection()
+            if selection then [selection] else []
+
+    onToggle: (isOpen) ->
+        @collection.fetch(limit: @props.displayLimit) if isOpen
+        @setState({isOpen})

     renderEdit: (label) ->
         Component = if @props.multi
@@ -56,13 +75,19 @@
             Lanes.Vendor.ReactWidgets.Combobox
         props = _.omit(@props, 'label')
         select = <Component
+            ref="select"
+            open={@state.isOpen}
+            onToggle={@onToggle}
+            onSelect={@onSelect}
+            suggest={true}
             data={@_getChoices()}
             valueField="id"
             textField="label"
             onChange={@onChange}
             name={@props.name}
+            {...props}
             value={@getCurrentSelection().id}
-            {...props} />
+            />

         if @props.unstyled
             select


Remove extraneous parentheses

Remove extraneous parentheses

--- src/js/navbar_events.coffee
+++ src/js/navbar_events.coffee
@@ -1,5 +1,4 @@
-module.exports = -> ($ document).ready -> (
-    ($ '#nav-view-fullscreen').click -> (
-        toggleFullscreen (($ 'body')[0])
-    )
-)
+module.exports = ->
+    ($ document).ready ->
+        ($ '#nav-view-fullscreen').click ->
+            toggleFullscreen (($ 'body')[0])


Changed default velocity

Changed default velocity

--- game.coffee
+++ game.coffee
@@ -26,7 +26,7 @@
     @WIDTH:  200
     @HEIGHT:  300

-    @VELOCITY = 0.1
+    @VELOCITY = 1

     @use_collisions = true


Improved comment js

Improved comment js

--- app/assets/javascripts/crm_comments.js.coffee
+++ app/assets/javascripts/crm_comments.js.coffee
@@ -4,55 +4,30 @@
 # See MIT-LICENSE file or http://www.opensource.org/licenses/mit-license.php
 #------------------------------------------------------------------------------

-# When comments are added to an entity, disable the add button
-# and add a spinner to indicate request is processing
 (($) ->

-  addSpinnerToComments = ->
-    $('div.new_comment').each ->
-      container = $(this)
-      unless container.hasClass('withSpinner')
-        container.find('form').on 'submit', ->
-          container.find('form [type=submit]').attr("disabled", "disabled")
-          container.find('.spinner').show()
-        container.addClass("withSpinner")
+  toggleComment = (el) ->
+    $container = $(el).closest('div.new_comment')
+    baseId  = $container.attr('id').replace('_comment_new', '')
+    $post    = $container.find('#' + baseId + '_post')
+    $ask     = $container.find('#' + baseId + '_ask')
+    $comment = $container.find('#' + baseId + '_comment_comment')
+    $post.toggle()
+    $ask.toggle()
+    if $comment.is(":visible")
+      $container.find('form [type=submit]').removeAttr("disabled")
+      $container.find('.spinner').hide()
+      crm.textarea_user_autocomplete(baseId + '_comment_comment')
+      $comment.focus()

-  toggleComment = (container) ->
-    baseId  = container.attr('id').replace('_comment_new', '')
-    post    = container.find('#' + baseId + '_post')
-    ask     = container.find('#' + baseId + '_ask')
-    comment = container.find('#' + baseId + '_comment_comment')
-    post.toggle()
-    ask.toggle()
-    if comment.is(":visible")
-      container.find('form [type=submit]').removeAttr("disabled")
-      container.find('.spinner').hide()
-      comment.focus()
+  # Show/hide the comment form
+  $(document).on 'click', '.new_comment a.cancel, input[name=post_new_note]', ->
+    toggleComment(this)

-  addOpenCloseToComments = ->
-    $('div.new_comment').each ->
-      container = $(this)
-      unless container.hasClass('withOpenClose')
-        baseId = container.attr('id').replace('_comment_new', '')
-        post   = container.find('#' + baseId + '_post')
-        ask    = container.find('#' + baseId + '_ask')
-        container.find('.cancel').on 'click', (event) ->
-          toggleComment(container)
-          false
-        new_comment = container.find('#' + baseId + '_post_new_note')
-        new_comment.on 'click', ->
-          toggleComment(container)
-        crm.textarea_user_autocomplete(baseId + '_comment_comment')
-        container.addClass("withOpenClose")
-
-  # Apply when document is loaded
-  $(document).ready ->
-    addSpinnerToComments()
-    addOpenCloseToComments()
-
-  # Apply when jquery event (e.g. search) occurs
-  $(document).ajaxComplete ->
-    addSpinnerToComments()
-    addOpenCloseToComments()
+  # When comment form is submitted, disable the form button and show the spinner
+  $(document).on 'click', 'div.new_comment [type=submit]', ->
+    $(this).attr("disabled", "disabled")
+    $(this).prev('.spinner').show()
+    $(this).closest('form').submit()

 )(jQuery)


Ignore hidden periods in category bar chart legend

--- app/assets/javascripts/d3/category_bar.coffee
+++ app/assets/javascripts/d3/category_bar.coffee
@@ -384,10 +384,14 @@
       target_series = []
       legend_series = []

+      include_present = @periods().includes('present')
+      include_future  = @periods().includes('future')
+
       for series in @series
         label = series.get('label')
-        total = Math.abs(series.safe_future_value()) +
-                Math.abs(series.safe_present_value())
+
+        total = (if include_future then Math.abs(series.safe_future_value()) else 0) +
+                (if include_present then Math.abs(series.safe_present_value()) else 0)

         if (series.get('is_target_line') || total > 1e-7) &&
             _.indexOf(seen_labels, label) == -1


added owner hash to cloud defaults.

added owner hash to cloud defaults.

--- app/assets/javascripts/models/cloud.js.coffee
+++ app/assets/javascripts/models/cloud.js.coffee
@@ -7,11 +7,15 @@
     name: ""
     description: ""
     avatar: {}
+    owner: {}
     is_transient: true

-  initialize: ->
+  initialize: (args) ->
+
+    args = {} unless args
+
     @type = 'cloud'
-
+
   removeAvatar: (options) ->
     attr = {}
     attr.remove_avatar = true


remove tabs console.log

remove tabs console.log

--- app/assets/javascripts/para/admin/tabs.coffee
+++ app/assets/javascripts/para/admin/tabs.coffee
@@ -14,8 +14,6 @@
   showActiveTab: ->
     if (hash = (location.hash or @$anchorInput?.val()))
       @findTab(hash).tab('show')
-
-    console.log 'tab', hash, @findTab(hash)

   onTabShown: (e) =>
     tabHash = $(e.target).attr('href')


Added Touch based menu opening and closing, however it is a little buggy so it is currently turned off by default.

--- app/assets/javascripts/static_pages.js.coffee
+++ app/assets/javascripts/static_pages.js.coffee
@@ -10,8 +10,27 @@
 #Menu Characteristics
 edgeLocation = "0%"
 mobileMenuWidth = "80%"
+negMobileMenuWidth = "-85%"
 desktopMenuWidth = "20%"
 mobileSiteWidth = "85%"
+
+#Turn on or off touch based menu sliding ("on"/"off")
+touchToggle = "off"
+
+maxTime = 1000
+maxDistance = 50
+startX = 0
+startTime = 0
+speed = 200
+animationState = "done"
+closed = "closed"
+open = "open"
+fixed = "fixed"
+relative = "relative"
+touch = "ontouchend" of document
+startEvent = (if (touch) then "touchstart" else "mousedown")
+moveEvent = (if (touch) then "touchmove" else "mousemove")
+endEvent = (if (touch) then "touchend" else "mouseup")

 changeMenuWidth = (e) ->
 	if ($(window).width() < ResponsiveWindowWidth)
@@ -19,18 +38,20 @@
 		$('.menu').data('sitewidth', mobileSiteWidth)
 		$(".menu").css("width", mobileMenuWidth)
 		$(".menu").css("left", "-" + mobileMenuWidth)
-		$('.siteContainer').css('left', edgeLocation)
-		$('body').css('position', "relative")
-		$(".menu").data("state", "closed")
+		$('.siteContainer').css 'left', edgeLocation, ->
+			$('body').css('position', "relative")
+			$(".menu").data("state", "closed")
+			animationState = "done"

 	if ($(window).width() > ResponsiveWindowWidth)
 		$(".menu").data("menuwidth", desktopMenuWidth)
 		$('.menu').data('sitewidth', desktopMenuWidth)
 		$(".menu").css("width", desktopMenuWidth)
 		$(".menu").css("left", "-" + desktopMenuWidth)
-		$('.siteContainer').css('left', edgeLocation)
-		$('body').css('position', "relative")
-		$(".menu").data("state", "closed")
+		$('.siteContainer').css 'left', edgeLocation, ->
+			$('body').css('position', "relative")
+			$(".menu").data("state", "closed")
+			animationState = "done"

 jQuery ->
 	$(window).bind("load", changeMenuWidth)
@@ -41,104 +62,66 @@
 	# Menu Open/Close Button
 	# if ($(window).width() > ResponsiveWindowWidth)
 	$('.btn-menu').click ->
-		closeSpeed = $('.menu').data('closespeed')
-		openSpeed = $('.menu').data('openspeed')
 		menuWidth = $('.menu').data('menuwidth')
 		edgeLocation = $('.menu').data('edgelocation')
 		siteWidth = $('.menu').data('sitewidth')

-		if $(".menu").data("state") == "open"
-			$('.menu').animate(left:"-" + menuWidth, closeSpeed)
-			$('.siteContainer').animate(left:edgeLocation, closeSpeed)
-			if ($(window).width() < ResponsiveWindowWidth)
-				$('body').css('position', "relative")
-			$(".menu").data("state", "closed")
+		if $(".menu").data("state") == "open" && animationState != "inProgress"
+			animationState = "inProgress"
+			$('.menu').animate(left:"-" + menuWidth, speed)
+			$('.siteContainer').animate left:edgeLocation, speed, ->
+				if ($(window).width() < ResponsiveWindowWidth)
+					$('body').css('position', "relative")
+				$(".menu").data("state", "closed")
+				animationState = "done"

-		else if $(".menu").data("state") == "closed"
-			$('.menu').animate(left:edgeLocation, openSpeed)
-			$('.siteContainer').animate(left:siteWidth, openSpeed)
-			if ($(window).width() < ResponsiveWindowWidth)
-				$('body').css('position', "fixed")
-			$(".menu").data("state", "open")
+		else if $(".menu").data("state") == "closed" && animationState != "inProgress"
+			animationState = "inProgress"
+			$('.menu').animate(left:edgeLocation, speed)
+			$('.siteContainer').animate left:siteWidth, speed, ->
+				if ($(window).width() < ResponsiveWindowWidth)
+					$('body').css('position', "fixed")
+				$(".menu").data("state", "open")
+				animationState = "done"

 	# This closes the menu when a link is pressed before loading the next page
 	$(".menuLink").click (e) ->
 		e.preventDefault()
 		$('.siteContainer').animate(
-			left: $('.menu').data('edgelocation')
+			left: edgeLocation
 		, $('.menu').data('closespeed'))
 		$(".menu").animate
 			left: "-" + $('.menu').data('menuwidth')
 		, $('.menu').data('closespeed'), ->
 			document.location.href = $(".menuLink").attr('href')

-	# if ($(window).width() < ResponsiveWindowWidth)
-	# 	$(".menu, .siteContainer").on "swipeleft", ->
-	# 		console.log("swipe left");
-	# 		if $(".menu").data("state") == "open"
-	# 			$('.menu').animate left:"-80%", 200
-	# 			$('.siteContainer').animate left: "0%", 200
-	# 			$('body').css('position', "relative")
-	# 			$(".menu").data("state", "closed")
+	if touchToggle == "on"
+		$(".siteContainer").bind startEvent, (e) ->
+			startTime = e.timeStamp
+			startX = (if e.originalEvent.touches then e.originalEvent.touches[0].pageX else e.pageX)

-	# 	$(".siteContainer").on "swiperight", ->
-	# 		console.log("swipe right" );
-	# 		if $(".menu").data("state") == "closed"
-	# 			$('.menu').animate left: "0%", 200, ->
-	# 				console.log("menu animation finished")
-	# 			$('.siteContainer').animate left: "85%", 200, ->
-	# 				console.log("siteContainer animation finished")
-	# 			$('body').css 'position', "fixed", ->
-	# 				console.log("position fixed")
-	# 			$(".menu").data "state", "open", ->
-	# 				console.log("state open")
+		$(".siteContainer").bind endEvent, (e) ->
+			startTime = 0
+			startX = 0

-	# 	$('.btn-menu').click ->
-	# 		if $(".menu").data("state") == "open"
-	# 			$('.menu').animate left:"-" + $('.menu').data('menuwidth'), 200, ->
-	# 				$('body').css('position', "relative")
-	# 				$(".menu").data("state", "closed")
-	# 			$('.siteContainer').animate(left: $('.menu').data('edgelocation'), 200)
-
-	# 		else if $(".menu").data("state") == "closed"
-	# 			$('.menu').animate left: $('.menu').data('edgelocation'), 200, ->
-	# 				$('body').css('position', "fixed")
-	# 				$(".menu").data("state", "open")
-	# 			$('.siteContainer').animate(left: $('.menu').data('sitewidth'), 200)
-
-# maxTime = 1000
-# maxDistance = 50
-# startX = 0
-# startTime = 0
-# touch = "ontouchend" of document
-# startEvent = (if (touch) then "touchstart" else "mousedown")
-# moveEvent = (if (touch) then "touchmove" else "mousemove")
-# endEvent = (if (touch) then "touchend" else "mouseup")
-
-# jQuery ->
-# 	$(".siteContainer").bind startEvent, (e) ->
-# 		startTime = e.timeStamp
-# 		startX = (if e.originalEvent.touches then e.originalEvent.touches[0].pageX else e.pageX)
-
-# 	$(".siteContainer").bind endEvent, (e) ->
-# 		startTime = 0
-# 		startX = 0
-
-# 	$(".siteContainer").bind moveEvent, (e) ->
-# 		currentX = (if e.originalEvent.touches then e.originalEvent.touches[0].pageX else e.pageX)
-# 		currentDistance = (if (startX is 0) then 0 else Math.abs(currentX - startX))
-# 		currentTime = e.timeStamp
-# 		if startTime != 0 && currentTime - startTime < maxTime && currentDistance > maxDistance
-# 			if($(window).width() <= ResponsiveWindowWidth)
-# 				if currentX < startX
-# 					if $(".menu").data("state") == "open"
-# 						$('.menu').animate(left:"-" + mobileMenuWidth, 200)
-# 						$('.siteContainer').animate(left:edgeLocation, 200)
-# 						$('body').css('position', "relative")
-# 						$(".menu").data("state", "closed")
-# 				if currentX > startX
-# 					if $(".menu").data("state") == "closed"
-# 						$('.menu').animate(left:edgeLocation, 200)
-# 						$('.siteContainer').animate(left:mobileSiteWidth, 200)
-# 						$('body').css('position', "fixed")
-# 						$(".menu").data("state", "open")+		$(".siteContainer").bind moveEvent, (e) ->
+			currentX = (if e.originalEvent.touches then e.originalEvent.touches[0].pageX else e.pageX)
+			currentDistance = (if (startX is 0) then 0 else Math.abs(currentX - startX))
+			currentTime = e.timeStamp
+			if startTime != 0 && currentTime - startTime < maxTime && currentDistance > maxDistance && animationState != "inProgress" && $(window).width() < ResponsiveWindowWidth
+				if currentX < startX
+					if $(".menu").data("state") == open
+						animationState = "inProgress"
+						$('.menu').animate left:negMobileMenuWidth, speed
+						$('.siteContainer').animate left:edgeLocation, speed, ->
+							$('body').css "position", relative
+							$(".menu").data "state", closed
+							animationState = "done"
+				if currentX > startX
+					if $(".menu").data("state") == closed
+						animationState = "inProgress"
+						$('.menu').stop().animate left:edgeLocation, speed
+						$('.siteContainer').animate left:mobileSiteWidth, speed, ->
+							$('body').css "position", fixed
+							$(".menu").data "state", open
+							animationState = "done"


ajout des deadlocks en z

ajout des deadlocks en z

--- app/assets/jax/models/deadlock_core.js.coffee
+++ app/assets/jax/models/deadlock_core.js.coffee
@@ -206,49 +206,34 @@
     deadlocked_positions = @deadlocked_z(cell.box, cell.down, cell.left, cell.down_right,
                                          pos.box,  pos.down,  deadlocked_positions)

-#    // fig 1, lower box
-#    if(posRight == -1 && posUpLeft == -1
-#        && boxesZone->readPos(posUp) == 1)
-#      if(goalBox == 0 || goalUp == 0)
-#        return true;
-#
-#    // fig 2, upper box
-#    if(posRight == -1 && posDownLeft == -1
-#        && boxesZone->readPos(posDown) == 1)
-#      if(goalBox == 0 || goalDown == 0)
-#        return true;
-#
-#    // fig 2, lower box
-#    if(posLeft == -1 && posUpRight == -1
-#        && boxesZone->readPos(posUp) == 1)
-#      if(goalBox == 0 || goalUp == 0)
-#        return true;
-#
-#    // fig 3, left box
-#    if(posUp == -1 && posDownRight == -1
-#        && boxesZone->readPos(posRight) == 1)
-#      if(goalBox == 0 || goalRight == 0)
-#        return true;
-#
-#    // fig 3, right box
-#    if(posDown == -1 && posUpLeft == -1
-#        && boxesZone->readPos(posLeft) == 1)
-#      if(goalBox == 0 || goalLeft == 0)
-#        return true;
-#
-#    // fig 4, left box
-#    if(posDown == -1 && posUpRight == -1
-#        && boxesZone->readPos(posRight) == 1)
-#      if(goalBox == 0 || goalRight == 0)
-#        return true;
-#
-#    // fig 4, right box
-#    if(posUp == -1 && posDownLeft == -1
-#        && boxesZone->readPos(posLeft) == 1)
-#      if(goalBox == 0 || goalLeft == 0)
-#        return true;
-#
-#
+    # fig 1, lower box
+    deadlocked_positions = @deadlocked_z(cell.box, cell.up, cell.right, cell.up_left
+                                         pos.box,  pos.up,  deadlocked_positions)
+
+    # fig 2, upper box
+    deadlocked_positions = @deadlocked_z(cell.box, cell.down, cell.right, cell.down_left
+                                         pos.box,  pos.down,  deadlocked_positions)
+
+    # fig 2, lower box
+    deadlocked_positions = @deadlocked_z(cell.box, cell.up, cell.left, cell.up_right
+                                         pos.box,  pos.up,  deadlocked_positions)
+
+    # fig 3, left box
+    deadlocked_positions = @deadlocked_z(cell.box, cell.right, cell.up, cell.down_right
+                                         pos.box,  pos.right,  deadlocked_positions)
+
+    # fig 3, right box
+    deadlocked_positions = @deadlocked_z(cell.box, cell.left, cell.down, cell.up_left
+                                         pos.box,  pos.left,  deadlocked_positions)
+
+    # fig 4, left box
+    deadlocked_positions = @deadlocked_z(cell.box, cell.right, cell.down, cell.up_right
+                                         pos.box,  pos.right,  deadlocked_positions)
+
+    # fig 4, right box
+    deadlocked_positions = @deadlocked_z(cell.box, cell.left, cell.up, cell.down_left
+                                         pos.box,  pos.left,  deadlocked_positions)
+
     return deadlocked_positions

   ###


Revert "Disable submit button on save click"

This reverts commit 99cca0573049a50f37cb9e0e7174693c3f16943a.

--- common/lib/xmodule/xmodule/js/src/capa/display.coffee
+++ common/lib/xmodule/xmodule/js/src/capa/display.coffee
@@ -412,13 +412,11 @@
       @save_internal()

   save_internal: =>
-    @enableCheckButton false
     Logger.log 'problem_save', @answers
     $.postWithPrefix "#{@url}/problem_save", @answers, (response) =>
       saveMessage = response.msg
       @gentle_alert saveMessage
       @updateProgress response
-      @enableCheckButton true

   refreshMath: (event, element) =>
     element = event.target unless element


Bootstrapper: Require `spark.ajax` namespace.

--- src/lib/Bootstrapper.coffee
+++ src/lib/Bootstrapper.coffee
@@ -22,6 +22,7 @@
 goog.require 'spark.components.Modal'

 goog.require 'spark.utils'
+goog.require 'spark.ajax'

 goog.require 'spark.widgets.SignUp'


ListFactory has factory for item

ListFactory has factory for item

--- src/lib/list-factory.coffee
+++ src/lib/list-factory.coffee
@@ -40,6 +40,14 @@
     getModelClass: ->
         {modelName, itemModelName} = @constructor
         @_ModelClass ?= @getFacade().getListModel(modelName, itemModelName)
+
+
+    ###*
+    @constructor
+    ###
+    constructor: ->
+        @itemFactory = @getFacade().createFactory(@constructor.itemModelName, true)
+        super

     ###*
@@ -117,10 +125,14 @@
         return new ListModel().setItems()

+    ###*
+    create item model
+
+    @method createItemFromObject
+    @return {BaseModel}
+    ###
     createItemFromObject: (obj) ->
-
-        itemFactory = @getFacade().createFactory(@constructor.itemModelName, true)
-        return itemFactory.createFromObject(obj)
+        return @itemFactory.createFromObject(obj)

 module.exports = ListFactory


things

things

--- src/instagram.coffee
+++ src/instagram.coffee
@@ -39,19 +39,10 @@
           msg.send item['images']['standard_resolution']['url']

 module.exports = (robot) ->
-  robot.respond /(kyle)( me )?(.*)/i, (msg) ->
-    count = 1
+  robot.respond /(wall)( me )?(.*)/i, (msg) ->
     authenticateUser(msg)
-    if msg.match[3]
-      text = msg.match[3].trim().split(" ")
-      tag =  text[0]
-      count = parseInt(text[1]) if text[1]
-    else
-      msg.send 'Please provied tag'
-      return
     Instagram.tags.search
       q: 'kyleinfrontofwalls'
-      count: count
       complete: (data) ->
         images = item['images']['standard_resolution']['url']
         msg.send images[Math.floor(Math.random() * images.length)]


removed unused method APLArray.get()

removed unused method APLArray.get()

--- src/array.coffee
+++ src/array.coffee
@@ -13,12 +13,6 @@
       for x, i in @stride then assert isInt x, -@data.length, @data.length + 1
     else
       assert prod(@shape) is 0
-
-  get: (indices) ->
-    p = @offset
-    for index, axis in indices
-      p += index * @stride[axis]
-    @data[p]

   empty: ->
     for d in @shape when not d then return true


Open issue #2

Open issue #2

--- src/array.coffee
+++ src/array.coffee
@@ -1,4 +1,6 @@
-# Additional math routines not found in standard JavaScript or SceneJS
+# Additional array routines not found in standard JavaScript or SceneJS
+
+# TODO: These modifications polute the global Array object, we need to limit this to a local copy of Array.

 #Array.prototype.flatten = (a) ->
 #	a.reduce ((xs, x) -> xs.concat flatten x if Array.isArray x else xs.concat [x]), []


Show full challenge text in kennnisland mode

--- core/app/backbone/views/facts/react_discussion.coffee
+++ core/app/backbone/views/facts/react_discussion.coffee
@@ -69,9 +69,12 @@
       _div ['top-annotation'],
         _div ['top-annotation-text'],
           if @model().get('displaystring')
-            ReactCollapsedText
+            if window.is_kennisland
               text: @model().get('displaystring')
-              size: 150
+            else
+              ReactCollapsedText
+                text: @model().get('displaystring')
+                size: 150
           else
             _div ["loading-indicator-centered"],
               ReactLoadingIndicator()


fix keyboard behavior on Firefox

fix keyboard behavior on Firefox

--- src/main/coffee/main.coffee
+++ src/main/coffee/main.coffee
@@ -178,15 +178,16 @@
         $(".modal[aria-hidden!='true']").length > 0

     _handlePostKeys: (e) =>
+        kc = e.keyCode || e.charCode
         # Scroll up/down one article.
         if this.articleList? && this.articleList.length > 0
-            if ((e.keyCode == 75 || e.keyCode == 107) && this.currentArticle?)
+            if ((kc == 75 || kc == 107) && this.currentArticle?)
                 # Mark current article as read before proceeding.
                 article = this.articleList.at this.currentArticle
                 if this.authedUser && article? && article.unread
                     this.togglePostAsRead article
                 this.currentArticle = this.currentArticle - 1
-            else if ((e.keyCode == 74 || e.keyCode == 106) && this.currentArticle <= this.articleList.length - 1)
+            else if ((kc == 74 || kc == 106) && this.currentArticle <= this.articleList.length - 1)
                 article = this.articleList.at this.currentArticle
                 if this.authedUser && article? && article.unread
                     # Mark current article as read before proceeding.
@@ -209,7 +210,8 @@
             e.preventDefault()

     _handleFeedKeys: (e) =>
-        if this.newsFeedView.canNavigateDownList() && (e.keyCode == 115 || e.keyCode == 83)
+        kc = e.keyCode || e.charCode
+        if this.newsFeedView.canNavigateDownList() && (kc == 115 || kc == 83)
             # s/S (navigate down list)
             initUrl = "/news/" + this._uid + "/feeds"
             nextFeed = this.newsFeedView.getNextFeed()
@@ -217,7 +219,7 @@
                 initUrl = initUrl + "/" + nextFeed
             this.navigate initUrl, true

-        else if this.newsFeedView.canNavigateUpList() && (e.keyCode == 119 || e.keyCode == 87)
+        else if this.newsFeedView.canNavigateUpList() && (kc == 119 || kc == 87)
             # w/W (navigate up list)
             initUrl = "/news/" + this._uid
             nextFeed = this.newsFeedView.getPrevFeed()
@@ -230,50 +232,51 @@
         e.preventDefault()

     _handleOpenArticleKeys: (e) =>
-         if this.articleList? && this.articleList.length > 0
-            if !this.currentArticle? || this.currentArticle < 0 || this.currentArticle >= this.articleList.length
-                this.currentArticle = 0
-
-            article = this.articleList.at this.currentArticle
-            articleId = article.article.id;
-            articleOffset = $("a[name='article" + articleId + "']").offset()
-            $('html, body').animate({
-                scrollTop: articleOffset.top - $("#top-nav-bar").height() - $("#ad-block").height() - $(".jumbotron").height()
-            }, 500)
-            e.preventDefault()
-
-            window.open article.article.link, "_blank"
-            if this.authedUser && article? && article.unread
-                this.togglePostAsRead article
+        if this.articleList? && this.articleList.length > 0
+           if !this.currentArticle? || this.currentArticle < 0 || this.currentArticle >= this.articleList.length
+               this.currentArticle = 0
+
+           article = this.articleList.at this.currentArticle
+           articleId = article.article.id;
+           articleOffset = $("a[name='article" + articleId + "']").offset()
+           $('html, body').animate({
+               scrollTop: articleOffset.top - $("#top-nav-bar").height() - $("#ad-block").height() - $(".jumbotron").height()
+           }, 500)
+           e.preventDefault()
+
+           window.open article.article.link, "_blank"
+           if this.authedUser && article? && article.unread
+               this.togglePostAsRead article

     _initializeKeyboardNavigation: ->
         # Set up keyboard navigation
         $(window).keypress (e) =>
             if not this._modalVisible()
-                if (e.keyCode == 74 || e.keyCode == 75 || e.keyCode == 106 || e.keyCode == 107)
+                kc = e.keyCode || e.charCode
+                if (kc == 74 || kc == 75 || kc == 106 || kc == 107)
                     # j/k/J/K (post navigation)
                     this._handlePostKeys e
-                else if (e.keyCode == 63)
+                else if (kc == 63)
                     # ? (help)
                     e.preventDefault()
                     $("#keyboardHelp").modal("show")
-                else if (e.keyCode == 119 || e.keyCode == 87 || e.keyCode == 115 || e.keyCode == 83)
+                else if (kc == 119 || kc == 87 || kc == 115 || kc == 83)
                     # w/W/s/S (feed navigation)
                     this._handleFeedKeys e
-                else if (e.keyCode == 114 || e.keyCode == 82)
+                else if (kc == 114 || kc == 82)
                     # r/R (mark all as read)
                     e.preventDefault()
                     this.markAllRead()
-                else if (e.keyCode == 100 || e.keyCode == 68)
+                else if (kc == 100 || kc == 68)
                     # d/D (deletes current feed)
                     e.preventDefault()
                     if not $("#removeFeedLink").parent().hasClass("disabled")
                         $("#removeFeedConfirm").modal()
-                else if (e.keyCode == 97 || e.keyCode == 65)
+                else if (kc == 97 || kc == 65)
                     # a/A (add new feed)
                     e.preventDefault()
                     this.showAddFeedWindow()
-                else if (e.keyCode == 79 || e.keyCode == 111)
+                else if (kc == 79 || kc == 111)
                     # o/O (open current article in new window)
                     this._handleOpenArticleKeys e


Remove Correct Spelling from mini editor context menu

--- menus/spell-check.cson
+++ menus/spell-check.cson
@@ -1,4 +1,4 @@
 'context-menu':
-  'atom-text-editor': [
+  'atom-text-editor:not([mini])': [
     {label: 'Correct Spelling', command: 'spell-check:correct-misspelling'}
   ]


handle halstead call nests

handle halstead call nests

--- src/chuck.coffee
+++ src/chuck.coffee
@@ -65,16 +65,19 @@
   if expression?.receiver?
     hals = [countExpressionHalstead expression.receiver]
     hals.push countExpressionHalstead expression.index if expression.index?
+    hals.push countExpressionHalstead expression.field if expression.field?
     hal = combineHalsteads hals
     hal.operators.push '[]'
     return hal
   if expression?.argv?
-    hal = combineHalsteads (countExpressionHalstead arg for arg in expression.argv)
-    hal.operands.push resolveContainer expression.callee
+    hals = (countExpressionHalstead arg for arg in expression.argv)
+    hals.push countExpressionHalstead expression.callee
+    hal = combineHalsteads hals
     hal.operators.push 'new' if expression.newAllocation?
     return hal
   if expression?.callee? and expression?.initializer?
-    hal = countExpressionHalstead expression.initializer
+    hals = (countExpressionHalstead init for init in expression.initializer)
+    hal = combineHalsteads hals
     hal.operands.push resolveContainer expression.callee
     hal.operators.push 'new'
     hal.operators.push '{}'
@@ -113,7 +116,7 @@
     return hal
   return {
     operators: []
-    operands: [expression]
+    operands: [resolveContainer expression]
   }

 calculateStatementComplexity = (statement, options) ->


Select input field's content on select event.

--- web/js/views/search_input_view.coffee
+++ web/js/views/search_input_view.coffee
@@ -8,6 +8,7 @@
           _.defer @afterTypeahead
           item
         minLength: 3
+      @$el.on 'focus', => @$el.select()

     getTypeaheadAddresses: (query, callback) =>
       params = $.param { query: query }


Fixing blank/undefined field issue for cards without subtypes

--- src/netrunner.coffee
+++ src/netrunner.coffee
@@ -49,7 +49,7 @@
   text = "\n"
   text += "*Title*: #{card.title}\n"
   text += "*Faction*: :#{card.faction.toLowerCase()}:\n"
-  text += "*Type*: #{card.type} - #{card.subtype}\n"
+  text += "*Type*: #{card.type} #{ if card.subtype then (' - ' + card.subtype) else '' }\n"
   if card.type == "Agenda"
     text += "*Adv/Pts*: #{card.advancementcost} \/#{card.agendapoints}\n"
   if card.type == "ICE" || card.type == "Upgrade" || card.type == "Asset"


fix(fullscreen): Restore fullscreen if app was closed in fullscreen

Fixes #671

--- src/nylas-env.coffee
+++ src/nylas-env.coffee
@@ -575,7 +575,8 @@
     browserWindow = @getCurrentWindow()
     {x, y, width, height} = browserWindow.getBounds()
     maximized = browserWindow.isMaximized()
-    {x, y, width, height, maximized}
+    fullScreen = browserWindow.isFullScreen()
+    {x, y, width, height, maximized, fullScreen}

   # Set the dimensions of the window.
   #
@@ -627,6 +628,7 @@
       dimensions = @getDefaultWindowDimensions()
     @setWindowDimensions(dimensions)
     @maximize() if dimensions.maximized and process.platform isnt 'darwin'
+    @setFullScreen(true) if dimensions.fullScreen

   storeWindowDimensions: ->
     dimensions = @getWindowDimensions()


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/color.coffee
+++ src/color.coffee
@@ -1573,7 +1573,7 @@
 names.each (element) ->
   lookup[element[1].toLowerCase().replace(/ /g, "")] = element[0]

-log lookup
+console.log lookup

 ###
   check for named colors in a hash table


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/color.coffee
+++ src/color.coffee
@@ -1,5 +1,3 @@
-test = "YO YO YO!"
-
 Color = (I) ->
   I ||= {}


Fix rendering on MSIE6

Fix rendering on MSIE6

--- src/gui/tabs/remote/index.coffee
+++ src/gui/tabs/remote/index.coffee
@@ -1,7 +1,7 @@
 ###
 Remotes tab
 ###
-t = require './html.coffee'
+t = require './html'
 tHint = require '../local/hint.html'

 exports.a = (pane)->
@@ -26,17 +26,17 @@
 arborize = (list)->
   tree = {}
   for z in list by -1
-    t = tree
+    q = tree
     for n in z.$[0]
-      t = t[" #{n}"] ||=
+      q = q[" #{n}"] ||=
         n: 0
         best: z
         down: {}
-      t.n++
-      if z.dist and t.dist != 0 and t.dist != z.dist
-        t.dist = if t.dist
+      q.n++
+      if z.dist and q.dist != 0 and q.dist != z.dist
+        q.dist = if q.dist
           0
         else
           z.dist
-      t = t.down
+      q = q.down
   tree


fixed last(?) image context snag

fixed last(?) image context snag

--- views/puzzle.coffee
+++ views/puzzle.coffee
@@ -235,9 +235,9 @@
     photo = @puzzle.puzzle_view.photo
     @photo_clip_context.drawImage(photo,xx,yy,@hex_box.width,@hex_box.height,0,0,@hex_box.width,@hex_box.height)

-    @mask = new MissingPiecesMask(app, app.grid)
-    pm_img = document.getElementById("piece-mask")
-    context = pm_img.getContext('2d')
+    @mask = new MissingPiecesMask(@puzzle, @puzzle.grid)
+    # pm_img = document.getElementById("piece-mask")
+    context = @pattern.img.getContext('2d')
     context.globalCompositeOperation = 'source-atop'
     context.drawImage(@photo_clip,0,0)
     context.globalCompositeOperation = 'source-over'
@@ -253,7 +253,7 @@
     @redraw.apply_redraw()
     @redraw.prepare_next_redraw(x,y)
     context = @puzzle.puzzle_view.context_canvas
-    context.drawImage(@piece_mask.img,x,y)
+    context.drawImage(@pattern.img,x,y)
     @reset_bounding_box(x,y)


fill any designated hex

fill any designated hex

--- views/puzzle.coffee
+++ views/puzzle.coffee
@@ -4,6 +4,8 @@

     @grid = new PuzzleGridModel
     @puzzle_view = new PuzzleView
+    @hx = new HexBuilder
+
     @piece = new PuzzlePiece(this)

@@ -113,30 +115,31 @@

 class HexBuilder

-###############
   constructor: () ->
+    @canvas = document.getElementById("puzzle-widget")
+    @context = @canvas.getContext("2d")
+    @colors = ["#cc5050","#5050cc","#50cccc","#50cc50","#cccc50","#cc50cc"]

-    @canvas = document.getElementById("canvas")
-    @context = @canvas.getContext("2d")
+    @fillhex(1,1,1)
+    @fillhex(1,2,0)
+    @fillhex(2,1,3)
+    @fillhex(2,2,4)
+    @fillhex(3,1,5)
+    @fillhex(3,2,0)

-    @colors = []

-    @img = document.getElementById("terrain")
-    @context.drawImage(@img,0,0)
-############
-
-  fillhex: (a,b,color) ->
-    x = 35+a*18
-    y = 29+b*24
-    y = y+12 if (a%2 == 0)
-    @context.fillStyle = color
+  fillhex: (a,b,c_no) ->
+    x = 106+a*14
+    y = 35+b*20
+    y = y+9 if (a%2 == 0)
+    @context.fillStyle = @colors[c_no]
     @context.beginPath()
     @context.moveTo(x,y)
-    @context.lineTo(x+11,y)
-    @context.lineTo(x+18,y+12)
-    @context.lineTo(x+12,y+25)
-    @context.lineTo(x-1,y+25)
-    @context.lineTo(x-6,y+12)
+    @context.lineTo(x+9,y)
+    @context.lineTo(x+14,y+9)
+    @context.lineTo(x+9,y+19)
+    @context.lineTo(x,y+19)
+    @context.lineTo(x-5,y+9)
     @context.lineTo(x,y)
     @context.fill()
     @context.closePath()
@@ -147,12 +150,11 @@

   constructor: () ->

-    alert("PuzzleView constructor")
     @canvas = document.getElementById("puzzle-widget")
     @context = @canvas.getContext("2d")

-    @img = document.getElementById("frame")
-    @context.drawImage(@img,100,30)
+#    @img = document.getElementById("frame")
+#    @context.drawImage(@img,100,30)

 #   #   #   #   #   #


refactor selection setting logic

refactor selection setting logic

--- src/selection.coffee
+++ src/selection.coffee
@@ -1,5 +1,17 @@
 Scribe = require('./scribe')

+compareRanges = (range1, range2) ->
+  return true if range1 == null and range2 == null
+  return false if range1 == null or range2 == null
+  startContainer1 = range1.startContainer ? range1.start.leafNode
+  startContainer2 = range2.startContainer ? range2.start.leafNode
+  endContainer1 = range1.endContainer ? range1.end.leafNode
+  endContainer2 = range2.endContainer ? range2.end.leafNode
+  startOffset1 = range1.startOffset ? range1.start.offset
+  startOffset2 = range2.startOffset ? range2.start.offset
+  endOffset1 = range1.endOffset ? range1.end.offset
+  endOffset2 = range2.endOffset ? range2.end.offset
+  return startContainer1 == startContainer2 and endContainer1 == endContainer2 and startOffset1 == startOffset2 and endOffset1 == endOffset2

 # DOM Selection API says offset is child index of container, not number of characters like Scribe.Position
 normalizeNativePosition = (node, offset) ->
@@ -116,14 +128,9 @@

   setRange: (range, silent = false) ->
     return unless @nativeSelection?
-    unless silent
-      # If we are not emitting change, we don't care what the cursor was
-      this.update(true) unless silent
-      return if range == @range or @range?.equals(range)
-    @range = range
-    if @range?
+    if range?
       nativeRange = rangy.createRangyRange()
-      _.each([@range.start, @range.end], (pos, i) ->
+      _.each([range.start, range.end], (pos, i) ->
         [node, offset] = Scribe.DOM.findDeepestNode(pos.leafNode, pos.offset)
         node = node.parentNode if node.tagName == "BR"              # Firefox does not like selections inside break tags
         offset = Math.min(Scribe.DOM.getText(node).length, offset)  # Should only occur at end of document
@@ -133,13 +140,13 @@
       @nativeSelection.setSingleRange(nativeRange)
     else
       @nativeSelection.removeAllRanges()
-    @editor.emit(Scribe.Editor.events.SELECTION_CHANGE, @range) unless silent
+    @editor.emit(Scribe.Editor.events.SELECTION_CHANGE, range) unless silent or range == @range or @range?.equals(range)
+    @range = range

   update: (silent = false) ->
-    range = this.getRange()
-    unless range == @range or @range?.equals(range)
-      @editor.emit(Scribe.Editor.events.SELECTION_CHANGE, range) unless silent
-      @range = range
+    nativeRange = normalizeNativeRange(this.getNativeRange())
+    unless compareRanges(nativeRange, @range)
+      this.setRange(_nativeRangeToRange.call(this, nativeRange), silent)

 module.exports = Scribe


fix announcement/discussion form in IE8. fixes #11493

$.serializeForm's use of _.toArray breaks in IE8 b/c IE8
doesn't accept a NodeList as an argument for
Array.prototype.slice.

this works as a NodeList, so the fixes leaves it there.

test plan:
  * in IE8, attempt to create a new discussion or announcement
    and verify that it posts and saves correctly.

Change-Id: Ie2b24f496efc133dff51da0b448c1a777f931f18
Reviewed-on: https://gerrit.instructure.com/14949
Tested-by: Jenkins <d95b56ce41a2e1ac4cecdd398defd7414407cc08@instructure.com>
Reviewed-by: Mark Ericksen <776ab05fc6b68e82d2b2c63873bf56edde131809@instructure.com>

--- app/coffeescripts/jquery/serializeForm.coffee
+++ app/coffeescripts/jquery/serializeForm.coffee
@@ -36,7 +36,6 @@

   $.fn.serializeForm = ->
     _.chain(this[0].elements)
-      .toArray()
       .filter(isInput)
       .map(getValue)
       .value()


add tests calling zlib.gzip directly (for debugging)

--- test/unit/coffee/ZipManager/ZipManager.coffee
+++ test/unit/coffee/ZipManager/ZipManager.coffee
@@ -4,6 +4,7 @@
 zipModulePath = "../../../../app/js/ZipManager"
 redisModulePath = "../../../../app/js/RedisManager"
 SandboxedModule = require('sandboxed-module')
+zlib = require('zlib')

 MIN_SIZE = 9999

@@ -57,6 +58,16 @@
 				@docLines.should.eql lines
 				done()

+	describe "calling node zlib.gzip directly", ->
+		it "should compress the string 'hello world' within the timeout", (done) ->
+			zlib.gzip "hello world", done
+
+		it "should compress a 10k string within the timeout", (done) ->
+			text = ""
+			while text.length < 10*1024
+				text = text + "helloworld"
+			zlib.gzip text, done
+
 	describe "for a large document (with compression enabled)", ->
 		rclient = null
 		beforeEach (done) ->
@@ -90,6 +101,7 @@
 			@docLines = []
 			while @docLines.join('').length <= MIN_SIZE
 				@docLines.push "this is a long line in a long document"
+			console.log "length of doclines", @docLines.join('').length
 			@callback = sinon.stub()
 			@RedisManager.setDocument @doc_id, @docLines, @version, () =>
 				@callback()


Server: FacebookCallback: handle user info error

--- servers/lib/server/facebook_callback.coffee
+++ servers/lib/server/facebook_callback.coffee
@@ -45,7 +45,12 @@
     rawResp = ''
     userInfoResp.on 'data', (chunk) -> rawResp += chunk
     userInfoResp.on 'end', ->
-      userInfo = JSON.parse rawResp
+      try userInfo = JSON.parse rawResp
+      catch e
+        return redirectToOauth 'Failed to parse user info', req, res, { provider }
+
+      unless userInfo?.name
+        return redirectToOauth 'No user name', req, res, { provider }

       [firstName, restOfNames...] = userInfo.name.split ' '
       lastName = restOfNames.join ' '


Two things: 1. Update documentation for `default-directory-search.coffee`. 2. Ensure that multiple `DirectorySearch` searches are run in series rather than in parallel to conserve resources.

--- src/default-directory-searcher.coffee
+++ src/default-directory-searcher.coffee
@@ -1,32 +1,73 @@
+{EventEmitter} = require 'events'
 Task = require './task'

-# Public:
+# Maintain a queue of ids of searches to run. When a search is complete, the active
+# search is cleared and the next search (if any) in the queue is notified to run.
+# This ensures there is at most one scan-handler task running at a time.
+searchQueue = []
+nextId = 1
+activeSearchId = 0
+emitter = new EventEmitter
+
+onSearchFinished = () ->
+  activeSearchId = null
+  runNextSearch()
+
+runNextSearch = () ->
+  unless activeSearchId
+    activeSearchId = searchQueue.shift()
+    emitter.emit(activeSearchId, null) if activeSearchId
+
+enqueue = (id) ->
+  searchQueue.push(id)
+  runNextSearch()
+
+
+# Public: Searches local files for lines matching a specified regex.
+#
 # Implements thenable so it can be used with `Promise.all()`.
 class DirectorySearch
-  # Public:
-  constructor: (directory, options) ->
+  # Public: Creates a new DirectorySearch that will not start running until the
+  # `emitter` that is private to this file emits an event with the specified `id`.
+  constructor: (directory, options, id) ->
     @task = new Task(require.resolve('./scan-handler'))
     rootPaths = [directory.getPath()]
     @promise = new Promise (resolve, reject) =>
-      @task.start(rootPaths, options.regexSource, options, resolve)
       @task.on('task:cancelled', reject)
+      emitter.once id, =>
+        @task.start(rootPaths, options.regexSource, options, resolve)

-  # Public:
+  # Public: Implementation of `then()` to satisfy the *thenable* contract.
+  # This makes it possible to use a `DirectorySearch` with `Promise.all()`.
+  #
   # Returns `Promise`.
   then: (args...) ->
     @promise.then.apply(@promise, args)

-  # Public:
+  # Public: Get notified when a search result is found.
+  #
+  # * `callback` {Function} called with a search result structured as follows:
+  #   * `searchResult` {Object} with the following keys:
+  #     * `filePath` {String} absolute path to the matching file.
+  #     * `matches` {Array} with object elements with the following keys:
+  #       * `lineText` {String} The full text of the matching line (without a line terminator character).
+  #       * `lineTextOffset` {Number} (This always seems to be 0?)
+  #       * `matchText` {String} The text that matched the `regex` used for the search.
+  #       * `range` {Range} Identifies the matching region in the file. (Likely as an array of numeric arrays.)
+  #
   # Returns `Disposable`.
   onDidMatch: (callback) ->
     @task.on 'scan:result-found', callback

-  # Public:
+  # Public: Get notified about any search errors.
+  #
+  # * `callback` {Function} called with an Error if there is a problem during the search.
+  #
   # Returns `Disposable`.
   onDidError: (callback) ->
     @task.on 'scan:file-error', callback

-  # Public:
+  # Public: Get notified with the number of paths searched thus far.
   #
   # * `callback` {Function} called with the number of paths searched thus far.
   #
@@ -34,10 +75,11 @@
   onDidSearchPaths: (callback) ->
     @task.on 'scan:paths-searched', callback

-  # Public:
+  # Public: Cancels the search.
   cancel: ->
     # This will cause @promise to reject.
     @task.cancel()
+    null

 # Default provider for the `atom.directory-searcher` service.
@@ -53,37 +95,31 @@
   # Public: Performs a text search for files in the specified `Directory`, subject to the
   # specified parameters.
   #
-  # Results are streamed back to the caller via `recordSearchResult()` and `recordSearchError()`.
+  # Results are streamed back to the caller by adding callbacks to the `DirectorySearch` returned by
+  # this method.
   #
   # * `directory` {Directory} that has been accepted by this provider's `canSearchDirectory()`
   # predicate.
-  # (Note this reflects the "Use Regex" option exposed via the ProjectFindView UI.)
-  # * `onSearchResult` {Function} Should be called with each matching search result.
-  #   * `searchResult` {Object} with the following keys:
-  #     * `filePath` {String} absolute path to the matching file.
-  #     * `matches` {Array} with object elements with the following keys:
-  #       * `lineText` {String} The full text of the matching line (without a line terminator character).
-  #       * `lineTextOffset` {Number} (This always seems to be 0?)
-  #       * `matchText` {String} The text that matched the `regex` used for the search.
-  #       * `range` {Range} Identifies the matching region in the file. (Likely as an array of numeric arrays.)
-  # * `onSearchError` {Function} Should be called to report a search error.
-  # * `onPathsSearched` {Function} callback that should be invoked periodically with the number of
-  # paths searched.
   # * `options` {Object} with the following properties:
   #   * `regexSource` {String} regex to search with. Produced via `RegExp::source`.
-  #   * `ignoreCase` {boolean}
+  #   * `ignoreCase` {boolean} reflects whether the regex should be run with the `i` option.
   #   * `inclusions` {Array} of glob patterns (as strings) to search within. Note that this
   #   array may be empty, indicating that all files should be searched.
   #
   #   Each item in the array is a file/directory pattern, e.g., `src` to search in the "src"
   #   directory or `*.js` to search all JavaScript files. In practice, this often comes from the
   #   comma-delimited list of patterns in the bottom text input of the ProjectFindView dialog.
-  #   * `ignoreHidden` {boolean}
-  #   * `excludeVcsIgnores` {boolean}
+  #   * `ignoreHidden` {boolean} whether to ignore hidden files.
+  #   * `excludeVcsIgnores` {boolean} whether to exclude VCS ignored paths.
   #   * `exclusions` {Array} similar to inclusions
-  #   * `follow` {boolean} whether symlinks should be followed
+  #   * `follow` {boolean} whether symlinks should be followed.
   #
-  # Returns a `DirectorySearch` that includes a `cancel()` method. If invoked before the `Proimse` is
-  # determined, it will reject the `Promise`.
+  # Returns a *thenable* `DirectorySearch` that includes a `cancel()` method. If `cancel()` is
+  # invoked before the `DirectorySearch` is determined, it will reject the `DirectorySearch`.
   search: (directory, options) ->
-    new DirectorySearch(directory, options)
+    id = nextId
+    nextId += 1
+    directorySearch = new DirectorySearch(directory, options, id)
+    directorySearch.then(onSearchFinished, onSearchFinished)
+    enqueue(id)
+    directorySearch


added refresh rate, attribute casting

added refresh rate, attribute casting

--- script/helix.coffee
+++ script/helix.coffee
@@ -4,7 +4,7 @@
 helix.config = {}
 helix.config.delimiter = /@([a-z0-9_]{1,20})/g
 helix.config.localStream = "/"
-helix.config.remoteStream = "http://stream.helix.to/"
+helix.config.remoteStream = "http://localhost:9000/"

 helix.loadedScripts = {}
@@ -325,12 +325,15 @@

         for key, value of definition
             ## define actions of this
-            if $.isFunction(value) # if key not in excludedKeys
+            if $.isFunction(value)
                 elPrototype[key] = value
             else
                 Object.defineProperty(elPrototype, key, {
                     value: value
                     writable: true })
+
+            if key is 'defined'
+                value()

         CustomElement = document.registerElement("#{tagName}", {
             prototype: elPrototype })
@@ -353,7 +356,7 @@
     element = document.createElement("#{tag}")
     for key, value of elOptions
         if value?
-            element.set(key, value)
+            element.setAttribute(key, value)

     return element

@@ -361,6 +364,7 @@
 helix.activeBases = []

 helix._freeze = false
+helix.frame = 0
 helix.start = () ->
     update = () ->
         if helix._freeze is true
@@ -369,7 +373,10 @@
         requestAnimationFrame(update)

         for element in helix.activeBases
-            element.update()
+            if helix.frame % element.refresh is 0
+                element.update()
+
+        helix.frame++

     update()

@@ -478,6 +485,7 @@

     extends: ''
     libs: []
+    refresh: 1
     template: ''

     ## built-in actions
@@ -509,10 +517,8 @@
     ## be careful about what you move around here

     attachedCallback: () ->
-        # @properties = $.extend({}, @properties)
-
         ## set non generic attributes as properties
-        @_setAttributes()
+        @_setAttributes()

         @setup()

@@ -558,7 +564,7 @@
     _setAttributes: () ->
         """iterate over bases attributes
                 append any specified base class
-                push the ids of any specified bridges
+                cast strings as floats (if applicable)
                 set all other attributes
         """
         for attr, attrMap of @attributes
@@ -575,6 +581,8 @@
                         value = true
                     else if attrValue in ['false', 'False']
                         value = false
+                    else if "#{attrValue}" is "#{parseFloat(attrValue)}"
+                        value = parseFloat(attrValue)
                     else
                         value = attrValue

@@ -582,7 +590,7 @@
                         @[name] = value

     _template: (str) ->
-        # replace delimited
+        # replace delimited character
         str = str.replace(helix.config.delimiter, (surroundedProperty) =>
             property = surroundedProperty.slice(1)
             value = @[property]
@@ -592,66 +600,4 @@
                 return surroundedProperty
         )

-})
-
-    ## the main properties
-
-# })
-
-
-
-    # preCreate: () ->
-    #     return
-
-    # create: () ->
-    #     return
-
-    # update: () ->
-    #     return
-
-    # remove: () ->
-    #     return
-
-    ## built ins
-
-
-
-    # get: (attribute, _default) ->
-    #     if @properties[attribute]?
-    #         attr = @properties[attribute]
-
-    #     parsedFloat = parseFloat(attr)
-    #     if "#{attr}" is "#{parsedFloat}"
-    #         return parsedFloat
-    #     else
-    #         if not attr?
-    #             return _default
-    #         else
-    #             return attr
-
-    # set: (attribute, value) ->
-    #     if @properties[attribute]? or typeof @properties[attribute] is 'undefined'
-    #         @properties[attribute] = value
-
-    #     if typeof value in ['string', 'number']
-    #         @setAttribute(attribute, value)
-
-    #     return @get(attribute)
-
-        # bind attributes
-        # slice = 0
-        # while slice < str.length
-        #     sliced = str.slice(slice, str.length)
-        #     split = sliced.match(regex.attributes)
-
-        #     if not split?
-        #         break
-
-        #     slice += split.index + split[0].length
-
-        # return str
-
-    ## DOM CALLBACKs
-
-    # createdCallback: () ->
-        # alert 'created'+})


Improve grammar

Improve grammar

--- def/ko/context.cson
+++ def/ko/context.cson
@@ -7,9 +7,9 @@
   "atom-text-editor, .overlayer":
     "core:undo": "실행취소"
     "core:redo": "다시실행"
-    "core:cut": "잘라내기"
+    "core:cut": "오려두기"
     "core:copy": "복사"
-    "core:paste": "붙여넣기"
+    "core:paste": "붙이기"
     "core:delete": "삭제"
     "core:select-all": "전체 선택"
     "pane:split-up-and-copy-active-item": "위로 분할"
@@ -49,14 +49,14 @@
   ".tab-bar":
     "pane:reopen-closed-item": "닫힌 탭 다시 열기"
   ".tree-view.full-menu":
-    "tree-view:add-file": "새 파일"
-    "tree-view:add-folder": "새 폴더"
+    "tree-view:add-file": "새로운 파일"
+    "tree-view:add-folder": "새로운 폴더"
     "tree-view:move": "이름 변경"
     "tree-view:duplicate": "복제"
     "tree-view:remove": "삭제"
     "tree-view:copy": "복사"
-    "tree-view:cut": "잘라내기"
-    "tree-view:paste": "붙여넣기"
+    "tree-view:cut": "오려두기"
+    "tree-view:paste": "붙이기"
     "tree-view:open-selected-entry-up": "위로 분할"
     "tree-view:open-selected-entry-down": "아래로 분할"
     "tree-view:open-selected-entry-left": "왼쪽으로 분할"
@@ -71,14 +71,14 @@
     "tree-view:open-selected-entry-left": "왼쪽으로 분할"
     "tree-view:open-selected-entry-right": "오른쪽으로 분할"
   ".tree-view.full-menu .project-root > .header":
-    "tree-view:add-file": "새 파일"
-    "tree-view:add-folder": "새 폴더"
+    "tree-view:add-file": "새로운 파일"
+    "tree-view:add-folder": "새로운 폴더"
     "tree-view:move": "이름 변경"
     "tree-view:duplicate": "복제"
     "tree-view:remove": "삭제"
     "tree-view:copy": "복사"
-    "tree-view:cut": "잘라내기"
-    "tree-view:paste": "붙여넣기"
+    "tree-view:cut": "오려두기"
+    "tree-view:paste": "붙이기"
     "tree-view:open-selected-entry-up": "위로 분할"
     "tree-view:open-selected-entry-down": "아래로 분할"
     "tree-view:open-selected-entry-left": "왼쪽으로 분할"
@@ -99,8 +99,8 @@
   ".tree-view.multi-select":
     "tree-view:remove": "삭제"
     "tree-view:copy": "복사"
-    "tree-view:cut": "잘라내기"
-    "tree-view:paste": "붙여넣기"
+    "tree-view:cut": "오려두기"
+    "tree-view:paste": "붙이기"
   "atom-pane[data-active-item-path] .item-views":
     "tree-view:reveal-active-file": "Tree View에서 보이기"
   "atom-pane[data-active-item-path] .tab.active":


Adjusted params.format setter.

Adjusted params.format setter.

--- src/tower/controller/instrumentation.coffee
+++ src/tower/controller/instrumentation.coffee
@@ -62,7 +62,8 @@
       @session  = @request.session  || {}

       unless @params.format
-        try @params.format = require('mime').extension(@request.header("content-type"))
+        console.log @request.header("content-type")
+        try @params.format = require('mime').extension(@controller.request.header("content-type"))
         @params.format ||= "html"

       @format   = @params.format


Removes console logs

Removes console logs

--- app/views/editor/level/thangs_tab_view.coffee
+++ app/views/editor/level/thangs_tab_view.coffee
@@ -225,9 +225,7 @@
     @editThang thangID: e.thang.id

   onRandomiseTerrain: (e) ->
-    console.log e
     for thang in e.thangs
-      console.log thang.id, thang.pos
       @selectAddThangType thang.id
       @addThang @addThangType, thang.pos

@@ -282,7 +280,6 @@
     @selectAddThang {target: icons[nextSelectedIndex]}

   selectAddThangType: (type, @cloneSourceThang) ->
-    console.log type
     if _.isString type
       type = _.find @supermodel.getModels(ThangType), (m) -> m.get('name') is type
     pos = @addThangSprite?.thang.pos  # Maintain old sprite's pos if we have it
@@ -400,7 +397,6 @@
     @editThang thangID: id if id

   addThang: (thangType, pos) ->
-    console.log thangType, pos
     thangID = Thang.nextID(thangType.get('name'), @world) until thangID and not @thangsTreema.get "id=#{thangID}"
     if @cloneSourceThang
       components = _.cloneDeep @thangsTreema.get "id=#{@cloneSourceThang.id}/components"


 Merge branch 'master.tb-fix' into 'master'

Master.Tb Fix

--- client/Main/CommonViews/tbcampaigncontroller.coffee
+++ client/Main/CommonViews/tbcampaigncontroller.coffee
@@ -36,6 +36,7 @@
       if hasUnder4GB
         KD.getSingleton("vmController").resizeDisk targetVMName, (err, res) =>
           return warn err  if err
+          KD.getSingleton("vmController").emit "ReferralCountUpdated"
           @showModal { userType: "under4GB" }
       else
         @showModal { userType: "above4GB" }


Sidebar: Added machine providers as class names to machine items.

--- client/Main/navigation/navigationmachineitem.coffee
+++ client/Main/navigation/navigationmachineitem.coffee
@@ -13,7 +13,7 @@
     path               = KD.utils.groupifyLink "/IDE/VM/#{machine.uid}"

     options.tagName    = 'a'
-    options.cssClass   = "vm #{machine.status.state.toLowerCase()}"
+    options.cssClass   = "vm #{machine.status.state.toLowerCase()} #{machine.provider}"
     options.attributes =
       href             : path
       title            : "Open IDE for #{@alias}"


 Merge branch 'master.activity.like' into 'master.activity'

activity: like summary view improvement

--- client/Social/Activity/views/likesummaryview.coffee
+++ client/Social/Activity/views/likesummaryview.coffee
@@ -53,14 +53,16 @@

     {actorsCount, actorsPreview} = @getData().interactions.like

-    linkCount = Math.min actorsPreview.length, 3
+    linkCount = switch
+      when actorsCount > 3 then 2
+      else actorsPreview.length

     for i in [0..linkCount - 1]
       @addSubView new ProfileLinkView null, accounts[i]
       @addTextElement partial: @getSeparatorPartial actorsCount, linkCount, i

     if (diff = actorsCount - linkCount) > 0
-      @addShowMoreLink()
+      @addShowMoreLink actorsCount, linkCount
       @addTextElement partial: " other#{if diff > 1 then 's' else ''}"

     @addTextElement partial: ' liked this.'
@@ -77,13 +79,11 @@
         ', '

-  addShowMoreLink: ->
-
-    {actorsCount} = @getData().interactions.like
+  addShowMoreLink: (actorsCount, linkCount) ->

     @addSubView new KDCustomHTMLView
       tagName : 'strong'
-      partial : actorsCount - 3
+      partial : actorsCount - linkCount
       click   : @bound 'showLikers'


activity: add ACTIVATE_LOADER_MARKER action type

--- client/activity/lib/flux/actions/actiontypes.coffee
+++ client/activity/lib/flux/actions/actiontypes.coffee
@@ -9,6 +9,8 @@

   'LOAD_MESSAGE_BY_SLUG_BEGIN'
   'LOAD_MESSAGE_BY_SLUG_FAIL'
+
+  'ACTIVATE_LOADER_MARKER'

   'CREATE_MESSAGE_BEGIN'
   'CREATE_MESSAGE_SUCCESS'


[Banning] added notification for else-case

--- client/app/MainApp/sidebar/modals/adminmodal.coffee
+++ client/app/MainApp/sidebar/modals/adminmodal.coffee
@@ -51,13 +51,11 @@
                 callback      : =>
                   accounts = @userController.getSelectedItemData()
                   if accounts.length > 0
-                    console.log accounts[0]
                     activityController = KD.getSingleton('activityController')
                     activityController.emit "ActivityItemBlockUserClicked", accounts[0].profile.nickname
-                    console.log "hede"
                   else
-                    console.log accounts
-
+                    new KDNotificationView {title: "Please select an account!"}
+
               Impersonate     :
                 label         : "Switch to User "
                 itemClass     : KDButtonView