removed code which does not seem to do anything

--- core/app/backbone/views/auto_completes_view.coffee
+++ core/app/backbone/views/auto_completes_view.coffee
@@ -84,9 +84,7 @@

   onClose: -> super()

-  onItemAdded: (view)->
-    super(view)
-    @options.mainView.$('.auto_complete').removeClass('empty')
+  onItemAdded: (view)-> super(view)

   showEmptyView: -> @$el.hide()
   closeEmptyView: -> @$el.show()


Add spec for JSON tokenizing with Unicode characters

--- spec/text-mate-grammar-spec.coffee
+++ spec/text-mate-grammar-spec.coffee
@@ -649,17 +649,28 @@
         expect(tokens[4].value).toEqual '"'
         expect(tokens[4].scopes).toEqual ["text.html.erb", "meta.embedded.line.erb", "string.quoted.double.ruby", "punctuation.definition.string.end.ruby"]

-    describe "Surrogate pair characters", ->
-      beforeEach ->
-        grammar = syntax.selectGrammar('main.js')
-        lines = grammar.tokenizeLines "'\uD835\uDF97'"
-
-      it "correctly parses JavaScript strings containing surrogate pair characters", ->
-        tokens = lines[0]
-        expect(tokens.length).toBe 3
-        expect(tokens[0].value).toBe "'"
-        expect(tokens[1].value).toBe "\uD835\uDF97"
-        expect(tokens[2].value).toBe "'"
+    describe "Unicode support", ->
+      describe "Surrogate pair characters", ->
+        beforeEach ->
+          grammar = syntax.selectGrammar('main.js')
+          lines = grammar.tokenizeLines "'\uD835\uDF97'"
+
+        it "correctly parses JavaScript strings containing surrogate pair characters", ->
+          tokens = lines[0]
+          expect(tokens.length).toBe 3
+          expect(tokens[0].value).toBe "'"
+          expect(tokens[1].value).toBe "\uD835\uDF97"
+          expect(tokens[2].value).toBe "'"
+
+      describe "when the line contains unicode characters", ->
+        it "correctly parses tokens starting after them", ->
+          atom.activatePackage('json-tmbundle', sync: true)
+          grammar = syntax.selectGrammar('package.json')
+          {tokens} = grammar.tokenizeLine '{"\u2026": 1}'
+
+          expect(tokens.length).toBe 8
+          expect(tokens[6].value).toBe '1'
+          expect(tokens[6].scopes).toEqual ["source.json", "meta.structure.dictionary.json", "meta.structure.dictionary.value.json", "constant.numeric.json"]

     describe "python", ->
       it "parses import blocks correctly", ->


Fix other flaky test re: adding new file

Similar to 55e1b25bc5315d60143859606523fd55cbef5f96, we need to wait for
the tree view selection to *fully* update before checking the selected
item in the tree view.

As far as I can tell, when a file is added, the tree view is updated in
a few steps:

1. Add the new file to the directory
2. Select the new file

Prior to this change, we were waiting for Step 1 to happen, and then
asserting that Step 2 had also already happened. Between Step 1 and Step
2, it appears that the *directory* is selected, and that was causing the
failure seen in
https://github.com/atom/tree-view/issues/1155#issuecomment-319471558.

--- spec/tree-view-package-spec.coffee
+++ spec/tree-view-package-spec.coffee
@@ -1837,11 +1837,14 @@
                 expect(atom.workspace.getModalPanels().length).toBe 0
                 expect(atom.workspace.getCenter().getActivePaneItem().getPath()).toBe newPath

-              waitsFor "tree view to be updated", ->
+              waitsFor "file to be added to tree view", ->
                 dirView3.entries.querySelectorAll(".file").length > 1

+              waitsFor "tree view selection to be updated", ->
+                treeView.element.querySelector('.file.selected') isnt null
+
               runs ->
-                expect(treeView.element.querySelector('.file.selected').textContent).toBe path.basename(newPath)
+                expect(treeView.element.querySelector('.selected').textContent).toBe path.basename(newPath)
                 expect(callback).toHaveBeenCalledWith({path: newPath})

           describe "when a file already exists at that location", ->


remove some unicode chars from the replacement regex


column headings in reverse cross tabulate

--- coffee/operations/reverse_cross_tabulate.coffee
+++ coffee/operations/reverse_cross_tabulate.coffee
@@ -25,7 +25,7 @@
     @elems.sidebar.innerHTML = ''

     Weya elem: @elems.sidebar, context: this, ->
-     @$.elems.btn = @button '.u-full-width.button-primary', 'Delete',
+     @$.elems.btn = @button '.u-full-width.button-primary', 'Convert to rows',
       on: {click: @$.on.apply}
       style: {display: 'none'}
      @button '.u-full-width', on: {click: @$.on.cancel}, 'Cancel'
@@ -78,7 +78,8 @@
      id = col.id
      sampleCol = col
      n++
-    id = "#{id}_0"
+    idHead = "#{id}_0"
+    id = "#{id}_1"

     data = {}
     for col, i in @table.columns when not @columns[i]
@@ -90,10 +91,12 @@
     @table.size *= n

     data[id] = new Array @table.size
+    data[idHead] = new Array @table.size
     m = 0
     for col, i in @table.columns when @columns[i]
      for d, j in @table.data[col.id]
       data[id][m + j * n] = d
+      data[idHead][m + j * n] = col.name
      m++

     columns = []
@@ -101,6 +104,11 @@
      if not @columns[i]
       columns.push col

+    columns.push
+     id: idHead
+     name: idHead
+     type: sampleCol.type
+     default: sampleCol.default
     columns.push
      id: id
      name: id


Fix pad calculation for corner concave oscillators

--- src/pattern/default/common/calculator.coffee
+++ src/pattern/default/common/calculator.coffee
@@ -419,7 +419,9 @@
       if housing.padWidth?
         pad.width = housing.padWidth
         if housing.padSpace? then pad.distance = housing.padSpace + housing.padWidth
+        if housing.padSpace1? then pad.distance1 = housing.padSpace1 + housing.padWidth
         if housing.padSpan? then pad.distance = housing.padSpan - housing.padWidth
+        if housing.padSpan1? then pad.distance1 = housing.padSpan1 - housing.padWidth
       if housing.padWidth1?
         pad.width1 = housing.padWidth1
         if housing.padSpace? then pad.distance1 = housing.padSpace + housing.padWidth1
@@ -433,7 +435,11 @@
         if housing.padSpan? then pad.distance2 = housing.padSpan - housing.padWidth2
         if housing.padSpan2? then pad.distance2 = housing.padSpan2 - housing.padWidth2

-      if housing.padHeight? then pad.height = housing.padHeight
+      if housing.padHeight?
+        pad.height = housing.padHeight
+        if housing.padSpace2? then pad.distance2 = housing.padSpace2 + housing.padHeight
+        if housing.padSpan2? then pad.distance2 = housing.padSpan2 - housing.padHeight
+
       if housing.padHeight1? then pad.height1 = housing.padHeight1
       if housing.padHeight2? then pad.height2 = housing.padHeight2


Highlight w-extend attribute

Highlight w-extend attribute

--- grammars/marko.cson
+++ grammars/marko.cson
@@ -470,7 +470,7 @@
     'match': '(?<=[^=])\\b([a-zA-Z0-9:-]+)'
     'name': 'entity.other.attribute-name.html'
   'tag-marko-attribute':
-    'match': '(?<=[^=])\\b((if|for|else-if|body-only-if|attrs|w-bind|w-config|w-el-id|w-for|w-id)\\s*=|(else)\\b)'
+    'match': '(?<=[^=])\\b((if|for|else-if|body-only-if|attrs|w-bind|w-extend|w-config|w-el-id|w-for|w-id)\\s*=|(else)\\b)'
     'captures':
       '2':
         'name': 'support.function.marko_attribute'


color ++ and -- in local definitions

color ++ and -- in local definitions

--- grammars/stata.cson
+++ grammars/stata.cson
@@ -190,6 +190,8 @@
     'beginCaptures':
       '1':
         'name': 'storage.modifier.macro.test.stata'
+      '3':
+        'name': 'keyword.operator.arithmetic.stata'
     'end': '(?=:|\\"|\\s|\\n|/|,)'
     'patterns': [
       {


Color macros better in list extended function - see `help macrolists` - Fixes #75

--- grammars/stata.cson
+++ grammars/stata.cson
@@ -799,8 +799,29 @@
         name: 'keyword.macro.extendedfcn.stata'
       }
       {
-        match: '\\b(list)\\b'
-        name: 'keyword.macro.extendedfcn.stata'
+        match: '\\b(list)\\s+(uniq|dups|sort|clean|retok(enize|eniz|eni|en|e)?|sizeof)\\s+(\\w{1,32})'
+        captures:
+          1: name: 'keyword.macro.extendedfcn.stata'
+          2: name: 'keyword.macro.extendedfcn.stata'
+          3: name: 'entity.name.type.class.stata'
+      }
+      {
+        match: '\\b(list)\\s+(\\w{1,32})\\s+(\\||&|\\-|===|==|in)\\s+(\\w{1,32})'
+        captures:
+          1: name: 'keyword.macro.extendedfcn.stata'
+          2: name: 'entity.name.type.class.stata'
+          3: name: 'keyword.operator.list.stata'
+          4: name: 'entity.name.type.class.stata'
+      }
+      {
+        match: '\\b(list\\s+posof)\\s+(")(\\w+)(")\\s+(in)\\s+(\\w{1,32})'
+        captures:
+          1: name: 'keyword.macro.extendedfcn.stata'
+          2: name: 'punctuation.definition.string.begin.stata'
+          3: name: 'string.quoted.double.stata'
+          4: name: 'punctuation.definition.string.end.stata'
+          5: name: 'keyword.macro.extendedfcn.stata'
+          6: name: 'entity.name.type.class.stata'
       }
       {
         match: '\\b(rown(ames|ame|am|a)?|coln(ames|ame|am|a)?|rowf(ullnames|ullname|ullnam|ullna|ulln|ull|ul|u)?|colf(ullnames|ullname|ullnam|ullna|ulln|ull|ul|u)?|roweq?|coleq?|rownumb|colnumb|roweqnumb|coleqnumb|rownfreeparms|colnfreeparms|rownlfs|colnlfs|rowsof|colsof|rowvarlist|colvarlist|rowlfnames|collfnames)\\b'


black outline seems more appropriate

black outline seems more appropriate

--- graphics.coffee
+++ graphics.coffee
@@ -480,7 +480,7 @@
       return
     mode_appearance = @mode_appearance[mode]
     if mode_appearance.invert
-      @ctx.strokeStyle = 'white'
+      @ctx.strokeStyle = 'black'
       @ctx.fillStyle = 'white'
     else
       @ctx.strokeStyle = 'white'
@@ -765,11 +765,13 @@
     return

   renderCommand: (command, size) ->
+    @ctx.save()
     switch command.type
       when 'move'
         @renderArrow(command.dir.theta, size)
       when 'mode'
         @renderBotMode(command.idx, size)
+    @ctx.restore()

   digit_graphics: [
     # 0


bugfix with pouchdb raw requests

bugfix with pouchdb raw requests

--- src/pouchmodel.coffee
+++ src/pouchmodel.coffee
@@ -208,10 +208,7 @@
                 callback err
             else
                 results = []
-                for doc in body.rows
-                    doc.value.id = doc.value._id
-                    results.push new @ doc.value
-                callback null, results
+                callback null, body.rows

     remove: (name, callback) ->
         docType = @getDocType()


project updated

project updated

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -15,21 +15,22 @@

 ###

-  alice()
-  backup([target])
-  convert()
-  daily()
-  josh()
-  jpeg([action])
-  lint()
-  list([target])
-  reboot(host)
-  seek([target])
-  sfacg(url)
-  shell([cmd])
-  ssserver(host)
-  upgrade()
-  wnacg()
+alice()
+backup([target])
+convert()
+daily()
+josh()
+jpeg([action])
+lint()
+list([target])
+reboot(host)
+seek([target])
+sfacg(url)
+shell([cmd])
+ssserver(host)
+upgrade()
+upgrade()
+wnacg()

 ###

@@ -197,6 +198,16 @@
   wnacg = new m()

   await wnacg.execute()
+
+$$.task 'upgrade', ->
+
+  await $$.shell [
+    'git stash'
+    'git stash clear'
+    'git pull'
+    'npm update'
+    'gulp prune'
+  ]

 $$.task 'z', ->


Fixing gulpfile

Fixing gulpfile

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -303,7 +303,7 @@
         # Just send the index.html for other files to support HTML5Mode
         res.sendFile("index.html", {root: "#{__dirname}/dist/"})

-    app.listen(9011)
+    app.listen(9001)

 # Rerun the task when a file changes
 gulp.task "watch", ->


runFlow에서 호출 함수 arity에 따라 인수 선택하게 버그 수정

runFlow에서 호출 함수 arity에 따라 인수 선택하게 버그 수정

--- handover.coffee
+++ handover.coffee
@@ -69,10 +69,8 @@

 runFlow = (fnFlows, err, args, outCallback)->
-  debug 'runFlow', arguments
-
+  errorHandlerArity = args.length + 2 # include err, callback
   if err
-    errorHandlerArity = args.length + 2 # include err, callback
     fnFlows = cutFlowsByArity(fnFlows, errorHandlerArity)

   return outCallback err, args... if fnFlows.length is 0
@@ -83,7 +81,7 @@
     fn = (args..., next)-> runForkFlow fnArr, args, next

   argsToCall = args
-  argsToCall = [err].concat args if err
+  argsToCall = [err].concat args if fn.length is errorHandlerArity

   fn argsToCall..., (err)->
     runFlow fns, err, args, outCallback
@@ -158,21 +156,7 @@
         outCallback err, output...
     argsToCall = args.concat fnDone
     fn argsToCall...
-
-_flow = (flowFns)->
-  return (args..., outCallback)->
-    first = args[0]
-    err = null
-    debug 'first', first
-    if first is null or first is undefined or _isError first
-      err = args.shift()
-      debug 'set err = ', err
-
-    if typeof outCallback isnt 'function'
-      args.push outCallback
-      outCallback = ()->
-
-    runFlow flowFns, err, args, outCallback
+

 _chain = (chainFns)->
   return (args..., outCallback)->
@@ -185,7 +169,7 @@
   return (args..., outCallback)->
     first = args[0]
     err = null
-    debug 'first', first
+    # debug 'first', first
     if first is null or first is undefined or _isError first
       err = args.shift()
       debug 'set err = ', err
@@ -194,6 +178,8 @@
       args.push outCallback
       outCallback = ()->

+    debug '_flow arity = ', args.length
+    debug '_flow err= ', err
     runFlow flowFns, err, args, outCallback


unbind event fixed

unbind event fixed

--- src/quo.events.coffee
+++ src/quo.events.coffee
@@ -125,7 +125,7 @@

     _findHandlers = (element_id, event, fn, selector) ->
         (HANDLERS[element_id] or []).filter (handler) ->
-            handler and (not event or handler.event is event) and (not fn or handler.fn is fn) and (not selector or handler.selector is selector)
+            handler and (not event or handler.event is event) and (not fn or handler.callback is fn) and (not selector or handler.selector is selector)

     _createProxy = (event) ->
         proxy = $$.extend( originalEvent: event, event)


A few fixes, better names, and case-insensitive search for query.

 * A typo prevented the label criterion from having an effect.
 * Query criterion is now case-insensitive.

--- src/scripts/github-issues.coffee
+++ src/scripts/github-issues.coffee
@@ -36,8 +36,8 @@

 # Given the text sent to robot.respond (e.g. 'hubot show me...'), parse the
 # criteria used for filtering issues.
-parse_criteria = (ask) ->
-  [me, limit, assignee, label, repo, query] = ask.match(ASK_REGEX)[1..]
+parse_criteria = (message) ->
+  [me, limit, assignee, label, repo, query] = message.match(ASK_REGEX)[1..]
   me: me,
   limit: parseInt limit.replace(" of", "") if limit?,
   assignee: assignee.replace("'s", "") if assignee?,
@@ -50,11 +50,11 @@
   { me, limit, assignee, label, repo, query } = criteria
   if assignee?
     issues = _.filter issues, (i) -> i.assignee? and i.assignee.login is assignee
-  if issue_label?
-    issues = _.filter issues, (i) -> _.any(i.labels, (l) -> l.name is issue_label)
+  if label?
+    issues = _.filter issues, (i) -> _.any(i.labels, (l) -> l.name is label)
   if query?
     issues = _.filter issues, (i) ->
-              _.any [i.body, i.title], (text) -> _s.include text.toLowerCase(), query
+              _.any [i.body, i.title], (text) -> _s.include text.toLowerCase(), query.toLowerCase()
   if limit?
     issues = _.first issues, parseInt limit
   issues
@@ -115,12 +115,12 @@
     assignee: (maybe one_of ["my", "@fred", "julia_roberts"]),
     label: (maybe one_of ["ui", "show-stopper"]),
     repo: (maybe one_of ["github/hubot", "hubot-scripts", "janky"]),
-    query: (maybe one_of ["firefox", "internet explorer"])
+    query: (maybe one_of ["firefox", "Internet Explorer"])

   # Create the string for the robot to receive from criteria. We create this
   # string from randomized criteria, then parse the string and compare the
   # results to the randomized criteria to test the `parse_criteria` function.
-  show_criteria = ({me, limit, assignee, label, repo, query}) -> [
+  criteria_to_message = ({me, limit, assignee, label, repo, query}) -> [
     'show', me,
     limit, 'of' if limit? and assignee?,
     (if assignee? and assignee isnt "my" then "#{assignee}'s" else assignee),
@@ -133,8 +133,8 @@
   # QuickCheck-inspired randomized test cases.
   _.times 100, ->
     criteria_expected = random_criteria()
-    ask = show_criteria criteria_expected
-    criteria_parsed = parse_criteria ask
+    message = criteria_to_message criteria_expected
+    criteria_parsed = parse_criteria message
     unless _.isEqual criteria_expected, criteria_parsed
       console.log "Counterexample: \"#{ask}\"\n\tExpected: #{pp criteria_expected}\n\tGot:      #{pp criteria_parsed}"


Updated mustachify to generate a psuedorandom mustache.

--- src/scripts/google-images.coffee
+++ src/scripts/google-images.coffee
@@ -17,6 +17,8 @@
       msg.send url

   robot.respond /(?:mo?u)?sta(?:s|c)he?(?: me)? (.*)/i, (msg) ->
+    type = Math.floor(Math.random() * 3)
+    mustachify = "http://mustachify.me/#{type}?src="
     imagery = msg.match[1]

     if imagery.match /^https?:\/\//i
@@ -24,8 +26,6 @@
     else
       imageMe msg, imagery, (url) ->
         msg.send "#{mustachify}#{url}"
-
-mustachify = "http://mustachify.me/?src="

 imageMe = (msg, query, cb) ->
   msg.http('http://ajax.googleapis.com/ajax/services/search/images')


add a little note about the shutdown method

--- test/test-worker-client.coffee
+++ test/test-worker-client.coffee
@@ -189,6 +189,7 @@
       (cb) ->
         job1.on 'complete', (handle, data) -> cb()
         new Worker 'test_shutdown_completion', (payload, worker) ->
+          # shutdown should only be called after done() once
           worker.parent.shutdown( ->
             console.warn "shutting down"
             cb new Error("called shutdown method before done called") if worker.parent.work_in_progress


fix issue with scoped pulseDuration/cursorThickness

--- lib/block-cursor.coffee
+++ lib/block-cursor.coffee
@@ -1,5 +1,16 @@
 'use strict'
 PackageConfigObserver = require 'atom-package-config-observer'
+
+equals = (obj, ref) ->
+  if obj is ref
+    return true
+  for own key, val of obj
+    if typeof val is 'object'
+      if not equals ref[key], val
+        return false
+    else if ref[key] isnt val
+      return false
+  return true

 class BlockCursor
   config:
@@ -97,13 +108,15 @@
     @stylesheet.parentNode.removeChild @stylesheet
     @stylesheet = null

-  updateGlobalCursorStyle: (globalConfig) =>
+  updateGlobalCursorStyle: (@globalConfig) =>
     @updateCursorStyleForScope globalConfig, [atom.workspace], ''
     for own scopeName, editors of @configObserver.editorsForObservedScopes()
       scopedConfig = @configObserver.configForScope scopeName
       @updateCursorStyleForScope scopedConfig, editors, scopeName

   updateCursorStyleForScope: (scopedConfig, editors, scopeName) =>
+    if scopedConfig isnt @globalConfig and equals scopedConfig, @globalConfig, scopeName
+      return
     scopedConfig = @prepareConfig scopedConfig
     @updateStylesheet scopeName, scopedConfig
     for editor in editors
@@ -133,9 +146,6 @@
     primaryColor.property = secondaryColor.property = switch cursorType
       when 'block' then 'background-color'
       else 'border-color'
-
-    pulseDuration = if pulseDuration > 0 then "#{pulseDuration}ms" else ''
-    cursorThickness = if cursorType isnt 'block' then "#{cursorThickness}px" else ''

     # transition opacity instead of background-color to transparent
     if secondaryColor.alpha is 0
@@ -161,8 +171,8 @@
     @stylesheet.sheet.insertRule """
       #{@selectorForScope scopeName} {
         #{primaryColor.property}: #{primaryColor.toRGBAString()};
-        #{if pulseDuration then "transition-duration: #{pulseDuration};" else ''}
-        #{if cursorThickness then "border-width: #{cursorThickness};" else ''}
+        transition-duration: #{pulseDuration}ms;
+        border-width: #{cursorThickness}px;
       }
     """, @cssRulesIndexes[scopeName]


Make status icons configurable

Make status icons configurable

--- src/stashboard.coffee
+++ src/stashboard.coffee
@@ -5,6 +5,9 @@
 #   HUBOT_STASHBOARD_TOKEN
 #   HUBOT_STASHBOARD_SECRET
 #   HUBOT_STASHBOARD_URL
+#   HUBOT_STASHBOARD_UP
+#   HUBOT_STASHBOARD_DOWN
+#   HUBOT_STASHBOARD_WARN
 #
 # Commands:
 #   hubot stashboard (status|?) - Display current stashboard status (via stupid hipchat icons)
@@ -23,9 +26,9 @@

 class Stashbot
   #hipchat icons, customize away
-  statusUp: '(successful)'
-  statusDown: '(failed)'
-  statusWarn: '(unknown)'
+  statusUp: process.env.HUBOT_STASHBOARD_UP || '(successful)'
+  statusDown: process.env.HUBOT_STASHBOARD_DOWN || '(failed)'
+  statusWarn: process.env.HUBOT_STASHBOARD_WARN || '(unknown)'

   constructor: (@robot, cb) ->
     if process.env.HUBOT_STASHBOARD_URL? and process.env.HUBOT_STASHBOARD_TOKEN? and process.env.HUBOT_STASHBOARD_SECRET?


better adaptation of speed in bended pieces


Use CompositeDisposable instead of SubscriberMixin in editor view

--- src/text-editor-component.coffee
+++ src/text-editor-component.coffee
@@ -14,12 +14,10 @@
 LinesComponent = require './lines-component'
 ScrollbarComponent = require './scrollbar-component'
 ScrollbarCornerComponent = require './scrollbar-corner-component'
-SubscriberMixin = require './subscriber-mixin'

 module.exports =
 TextEditorComponent = React.createClass
   displayName: 'TextEditorComponent'
-  mixins: [SubscriberMixin]

   pendingScrollTop: null
   pendingScrollLeft: null
@@ -57,6 +55,9 @@

   componentWillMount: ->
     @props.editor.manageScrollPosition = true
+
+    @disposables = new CompositeDisposable
+
     @observeConfig()
     @setScrollSensitivity(atom.config.get('editor.scrollSensitivity'))

@@ -99,12 +100,12 @@
     @observeEditor()
     @listenForDOMEvents()

-    @subscribe stylesElement.onDidAddStyleElement @onStylesheetsChanged
-    @subscribe stylesElement.onDidUpdateStyleElement @onStylesheetsChanged
-    @subscribe stylesElement.onDidRemoveStyleElement @onStylesheetsChanged
+    @disposables.add stylesElement.onDidAddStyleElement @onStylesheetsChanged
+    @disposables.add stylesElement.onDidUpdateStyleElement @onStylesheetsChanged
+    @disposables.add stylesElement.onDidRemoveStyleElement @onStylesheetsChanged
     unless atom.themes.isInitialLoadComplete()
-      @subscribe atom.themes.onDidChangeActiveThemes @onAllThemesLoaded
-    @subscribe scrollbarStyle.changes, @refreshScrollbars
+      @disposables.add atom.themes.onDidChangeActiveThemes @onAllThemesLoaded
+    @disposables.add scrollbarStyle.changes.onValue @refreshScrollbars

     @domPollingIntervalId = setInterval(@pollDOM, @domPollingInterval)

@@ -114,9 +115,9 @@
   componentWillUnmount: ->
     {editor, hostElement} = @props

-    @unsubscribe()
+    @disposables.dispose()
     @presenter.destroy()
-    @scopedConfigSubscriptions.dispose()
+    @scopedConfigDisposables.dispose()
     window.removeEventListener 'resize', @requestHeightAndWidthMeasurement
     clearInterval(@domPollingIntervalId)
     @domPollingIntervalId = null
@@ -227,9 +228,9 @@

   observeEditor: ->
     {editor} = @props
-    @subscribe editor.observeGrammar(@onGrammarChanged)
-    @subscribe editor.observeCursors(@onCursorAdded)
-    @subscribe editor.observeSelections(@onSelectionAdded)
+    @disposables.add editor.observeGrammar(@onGrammarChanged)
+    @disposables.add editor.observeCursors(@onCursorAdded)
+    @disposables.add editor.observeSelections(@onSelectionAdded)

   listenForDOMEvents: ->
     node = @getDOMNode()
@@ -282,24 +283,27 @@
         # clipboard.writeText is a sync ipc call on Linux and that
         # will slow down selections.
         ipc.send('write-text-to-selection-clipboard', selectedText)
-    @subscribe editor.onDidChangeSelectionRange ->
+    @disposables.add editor.onDidChangeSelectionRange ->
       clearTimeout(timeoutId)
       timeoutId = setTimeout(writeSelectedTextToSelectionClipboard)

   observeConfig: ->
-    @subscribe atom.config.onDidChange 'editor.fontSize', @sampleFontStyling
-    @subscribe atom.config.onDidChange 'editor.fontFamily', @sampleFontStyling
-    @subscribe atom.config.onDidChange 'editor.lineHeight', @sampleFontStyling
+    @disposables.add atom.config.onDidChange 'editor.fontSize', @sampleFontStyling
+    @disposables.add atom.config.onDidChange 'editor.fontFamily', @sampleFontStyling
+    @disposables.add atom.config.onDidChange 'editor.lineHeight', @sampleFontStyling

   onGrammarChanged: ->
     {editor} = @props

-    @scopedConfigSubscriptions?.dispose()
-    @scopedConfigSubscriptions = subscriptions = new CompositeDisposable
-
-    scopeDescriptor = editor.getRootScopeDescriptor()
-
-    subscriptions.add atom.config.observe 'editor.scrollSensitivity', scope: scopeDescriptor, @setScrollSensitivity
+    if @scopedConfigDisposables?
+      @scopedConfigDisposables.dispose()
+      @disposables.remove(@scopedConfigDisposables)
+
+    @scopedConfigDisposables = new CompositeDisposable
+    @disposables.add(@scopedConfigDisposables)
+
+    scope = editor.getRootScopeDescriptor()
+    @scopedConfigDisposables.add atom.config.observe 'editor.scrollSensitivity', {scope}, @setScrollSensitivity

   focused: ->
     if @isMounted()
@@ -526,10 +530,14 @@
   onSelectionAdded: (selection) ->
     {editor} = @props

-    @subscribe selection.onDidChangeRange => @onSelectionChanged(selection)
-    @subscribe selection.onDidDestroy =>
+    selectionDisposables = new CompositeDisposable
+    selectionDisposables.add selection.onDidChangeRange => @onSelectionChanged(selection)
+    selectionDisposables.add selection.onDidDestroy =>
       @onSelectionChanged(selection)
-      @unsubscribe(selection)
+      selectionDisposables.dispose()
+      @disposables.remove(selectionDisposables)
+
+    @disposables.add(selectionDisposables)

     if editor.selectionIntersectsVisibleRowRange(selection)
       @selectionChanged = true
@@ -542,7 +550,7 @@
       @requestUpdate()

   onCursorAdded: (cursor) ->
-    @subscribe cursor.onDidChangePosition @onCursorMoved
+    @disposables.add cursor.onDidChangePosition @onCursorMoved

   onCursorMoved: ->
     @cursorMoved = true


[Gutter][refactor] Simplify TextEditorPresenter::updateCustomGutterDecorationState (Pass 2)

--- src/text-editor-presenter.coffee
+++ src/text-editor-presenter.coffee
@@ -434,16 +434,12 @@
       for gutter in @model.getGutters()
         gutterName = gutter.name
         @state.gutters.customDecorations[gutterName] = {}
-        gutterState = @state.gutters.customDecorations[gutterName]
-
         return if !@gutterIsVisible(gutter)

         relevantDecorations = @customGutterDecorationsInRange(gutterName, @startRow, @endRow - 1)
-        return if !relevantDecorations
-
         relevantDecorations.forEach (decoration) =>
           decorationRange = decoration.getMarker().getScreenRange()
-          gutterState[decoration.id] =
+          @state.gutters.customDecorations[gutterName][decoration.id] =
             top: @lineHeight * decorationRange.start.row
             height: @lineHeight * decorationRange.getRowCount()
             item: decoration.getProperties().item
@@ -651,10 +647,10 @@
   # TODO (jssln) This needs tests.
   # Returns a {Set} of {Decoration}s on the given custom gutter from startRow to endRow (inclusive).
   customGutterDecorationsInRange: (gutterName, startRow, endRow) ->
-    return null if @model.isMini() or gutterName is 'line-number'
-
     decorations = new Set
-    return decorations if !@customGutterDecorationsByGutterNameAndScreenRow[gutterName]
+
+    return decorations if @model.isMini() or gutterName is 'line-number' or
+      !@customGutterDecorationsByGutterNameAndScreenRow[gutterName]

     for bufferRow in @model.bufferRowsForScreenRows(@startRow, @endRow - 1)
       for id, decoration of @customGutterDecorationsByGutterNameAndScreenRow[gutterName][bufferRow]


Tree context menu identifies actions properly

--- src/textorum/tinymce/tree.coffee
+++ src/textorum/tinymce/tree.coffee
@@ -103,44 +103,51 @@
         holder.unshift holder[0]['children'][holder[0]['children'].length - 1]
       true

+  # Return a function that produces editor-specific context menu items
   _contextMenuItemsGenerator = (editor) ->
-    _getSubmenu = (keys) ->
-      inserts = {}
-      inserted = false
-      for key of keys
-        inserted = true
-        inserts[key] =
-          label: key
-          icon: "img/tag.png"
-          action: (obj) ->
-            actionType = obj.parents("li.submenu").children("a").attr("rel")
-            key = obj.text()
-            pos =
-              x: parseInt($("#tree_popup").css("left"))
-              y: parseInt($("#tree_popup").css("top"))
-
-            if actionType is "change"
-              id = $("#tree a.ui-state-active").closest("li").attr("name")
-              editor.execCommand "changeTag",
-                key: key
-                pos: pos
-                id: id
-
-            else
-              editor.currentBookmark = editor.selection.getBookmark(1)
-              editor.execCommand "addSchemaTag",
-                key: key
-                pos: pos
-                action: actionType
-
-      unless inserted
-        inserts["no_tags"] =
-          label: "No tags available."
-          icon: "img/cross.png"
-          action: (obj) ->
-      inserts
-
-
+    # Return a function suitable for use as a jstree contextmenu action, given
+    # the action type ("before", "change") and key (target element name)
+    _submenuActionGenerator = (actionType, key) ->
+      (obj) ->
+        pos =
+          x: parseInt($("#tree_popup").css("left"))
+          y: parseInt($("#tree_popup").css("top"))
+        if actionType is "change"
+          #id = $("#tree a.ui-state-active").closest("li").attr("name")
+          id = $(obj).attr("name")
+          console.log "change", id, "to", key
+          editor.execCommand "changeTag",
+            key: key
+            pos: pos
+            id: id
+
+        else
+          editor.currentBookmark = editor.selection.getBookmark(1)
+          editor.execCommand "addSchemaTag",
+            key: key
+            pos: pos
+            action: actionType
+    # Given a list of keys, return a function to generate a list of submenu
+    # items for a given action
+    _submenuItemsForAction = (keys) ->
+      (action) ->
+        inserts = {}
+        inserted = false
+        for key of keys
+          inserted = true
+          inserts["#{action}-#{key}"] =
+            label: key
+            icon: "img/tag.png"
+            action: _submenuActionGenerator(action, key)
+
+        unless inserted
+          inserts["no_tags"] =
+            label: "No tags available."
+            icon: "img/cross.png"
+            action: (obj) ->
+        inserts
+
+    # The returned function for _contextMenuItemsGenerator
     contextMenuItems = (node) ->
       schema = editor.plugins.textorum.schema
       if not node.attr('data-xmlel')
@@ -158,33 +165,33 @@
         else
           {}
       )
-      submenu = _getSubmenu(validNodes)
-      siblingSubmenu = _getSubmenu(siblingNodes)
+      submenu = _submenuItemsForAction(validNodes)
+      siblingSubmenu = _submenuItemsForAction(siblingNodes)
       items =
         before:
           label: "Insert Tag Before"
           icon: "img/tag_add.png"
           _class: "submenu"
-          submenu: siblingSubmenu
+          submenu: siblingSubmenu("before")

         after:
           label: "Insert Tag After"
           icon: "img/tag_add.png"
           _class: "submenu"
-          submenu: siblingSubmenu
+          submenu: siblingSubmenu("after")

         inside:
           label: "Insert Tag Inside"
           icon: "img/tag_add.png"
           _class: "submenu"
           separator_after: true
-          submenu: submenu
+          submenu: submenu("inside")

         change:
           label: "Change Tag"
           icon: "img/tag_edit.png"
           _class: "submenu"
-          submenu: siblingSubmenu
+          submenu: siblingSubmenu("change")

         edit:
           label: "Edit Tag"


Remove testing view

Remove testing view

--- lib/debug-window.coffee
+++ lib/debug-window.coffee
@@ -1,16 +0,0 @@
-{View} = require 'atom'
-
-module.exports =
-
-class VimDebugView extends View
-  @content: >
-    @div outlet: 'main', class: 'debug-window', =>
-      @div class: 'keys'
-      @div class: 'commands'
-      @div class: 'register'
-
-  initialize: (@state)->
-    # add some events?
-
-  toggle: =>
-    @main.toggleClass('hidden')


Add empty 'addOne' method to collection view

--- src/views/base/collection.coffee
+++ src/views/base/collection.coffee
@@ -24,3 +24,5 @@

     @collection.each (model, index) =>
       @addOne model, { index }
+
+  addOne: ->


applies to all themes

applies to all themes

not just core

--- lib/package-card.coffee
+++ lib/package-card.coffee
@@ -64,9 +64,10 @@
       @installButton.remove()
       @uninstallButton.remove()

-    # core themes only have a settings option, no status
-    if atom.packages.isBundledPackage(@pack.name) and @type is 'theme'
+    # themes have no status and cannot be dis/enabled
+    if @type is 'theme'
       @statusIndicator.remove()
+      @enablementButton.remove()

     unless @hasSettings(@pack)
       @settingsButton.remove()


Treat EPERM as ENOENT for project not found - also fixes Windows specs

--- lib/project-view.coffee
+++ lib/project-view.coffee
@@ -81,7 +81,7 @@
         # throw ENOENT when it tries to get the realpath of all the project paths.
         # This catch block allows the file finder to still operate on the last
         # set of paths and still let the user know that something is wrong.
-        if error.code is 'ENOENT'
+        if error.code is 'ENOENT' or error.code is 'EPERM'
           atom.notifications.addError('Project path not found!', detail: error.message)
         else
           throw error


Add support for ocaml

Add support for ocaml

--- lib/grammars.coffee
+++ lib/grammars.coffee
@@ -199,6 +199,11 @@
         command: "bash"
         args: (context) -> ['-c', "xcrun clang++ -fcolor-diagnostics -Wc++11-extensions -Wall -include stdio.h -include iostream -framework Cocoa " + context.filepath + " -o /tmp/objc-cpp.out && /tmp/objc-cpp.out"]

+  ocaml:
+    "File Based":
+      command: "ocaml"
+      args: (context) -> [context.filepath]
+
   PHP:
     "Selection Based":
       command: "php"


Fix `m` command repeatable where it shouldn't

--- lib/operator.coffee
+++ lib/operator.coffee
@@ -621,8 +621,10 @@
 class Mark extends Operator
   @extend()
   # hover: icon: ':mark:', emoji: ':round_pushpin:'
+  recordable: false
   requireInput: true
   requireTarget: false
+  acceptPersistentSelection: false
   initialize: ->
     @focusInput()


#200 cleanup

#200 cleanup

--- lib/operator.coffee
+++ lib/operator.coffee
@@ -20,7 +20,6 @@
   constructor: (@message) ->
     @name = 'Operator Error'

-# General Operator
 # -------------------------
 class Operator extends Base
   @extend(false)
@@ -121,10 +120,9 @@
       timeout: settings.get('flashOnOperateDuration')

   mutateSelections: (fn) ->
-    return unless @selectTarget()
-    @editor.transact =>
-      for selection in @editor.getSelections()
-        fn(selection)
+    if @selectTarget()
+      @editor.transact =>
+        fn(selection) for selection in @editor.getSelections()

   execute: ->
     @mutateSelections (selection) =>
@@ -139,7 +137,7 @@
   execute: ->
     @selectTarget()
     return if @isMode('operator-pending') or @isMode('visual', 'blockwise')
-    unless @isMode('visual')
+    if not @isMode('visual')
       submode = swrap.detectVisualModeSubmode(@editor)
       @activateMode('visual', submode)
     else
@@ -366,7 +364,6 @@
   @extend()
   @description: "Transform string by specified oprator selected from select-list"
   requireInput: true
-  requireTarget: true
   # Member of transformers can be either of
   # - Operation class name: e.g 'CamelCase'
   # - Operation class itself: e.g. CamelCase
@@ -552,11 +549,10 @@

   onConfirm: (@input) ->
     # FIXME: dont manage allowNextLine independently. Each Pair text-object can handle by themselvs.
-    target = @new 'Pair',
+    @setTarget @new 'Pair',
       pair: @getPair(@input)
       inner: false
-      allowNextLine: @input in @pairChars
-    @setTarget(target)
+      allowNextLine: (@input in @pairChars)
     @processOperation()

   getNewText: (text) ->
@@ -856,7 +852,7 @@
         @setMarkForChange(newRange)
         @flash(newRange) if @needFlash()

-    if @selectPastedText# and haveSomeSelection(@editor)
+    if @selectPastedText
       submode = swrap.detectVisualModeSubmode(@editor)
       unless @isMode('visual', submode)
         @activateMode('visual', submode)
@@ -937,7 +933,7 @@
   requireInput: true

   initialize: ->
-    @setTarget @new('MoveRight') if @isMode('normal')
+    @setTarget(@new('MoveRight')) if @isMode('normal')
     @focusInput()

   getInput: ->


change order

change order

--- lib/settings.coffee
+++ lib/settings.coffee
@@ -36,12 +36,12 @@

   observeConditionalKeymaps: ->
     conditionalKeymaps =
+      keymapUnderscoreToReplaceWithRegister:
+        'atom-text-editor.vim-mode-plus:not(.insert-mode)':
+          '_': 'vim-mode-plus:replace-with-register'
       keymapCCToChangeInnerSmartWord:
         'atom-text-editor.vim-mode-plus.operator-pending-mode.change-pending':
           'c': 'vim-mode-plus:inner-smart-word'
-      keymapUnderscoreToReplaceWithRegister:
-        'atom-text-editor.vim-mode-plus:not(.insert-mode)':
-          '_': 'vim-mode-plus:replace-with-register'
       keymapSemicolonToInnerAnyPairInOperatorPendingMode:
         'atom-text-editor.vim-mode-plus.operator-pending-mode':
           ';': 'vim-mode-plus:inner-any-pair'


remove unnecessary streams module

remove unnecessary streams module

--- plugin/browserify.coffee
+++ plugin/browserify.coffee
@@ -11,9 +11,6 @@

 # use to hold file content as readable and get source map as writable
 strung = npm.require 'strung'
-
-# get 'stream' to use PassThrough to provide a Buffer as a Readable stream
-stream = npm.require 'stream'

 # use OS agnostic and fiber friendly versions of fs and path
 fs = Plugin.fs


Fix issue where item.text is not defined as expected

--- coffee/lib/callback-data-source.coffee
+++ coffee/lib/callback-data-source.coffee
@@ -29,7 +29,8 @@
     item = @results[child.value] || child

     item.array_index = item.value
-    item.html = item.label || item if not item.html?
+    item.text = item.label || item if not item.text?
+    item.html = item.text if not item.html?
     item.selected = item.selected || false
     item.disabled = item.disabled || false


log when more than one match found

log when more than one match found

--- coffeescript/service/dispatcher.coffee
+++ coffeescript/service/dispatcher.coffee
@@ -34,9 +34,10 @@
             action_name: action_name

+  # collect all the values from the interface description
+  # that we will need to match against.
    create_match_sequence: (path, action_name, definition) ->
-    # collect all the values from the interface description
-    # that we will need to match against.
+
     method = definition.method

     if definition.query
@@ -110,6 +111,14 @@
       results
     else
       matches = @compile_matches(results)
+      if matches.length > 1
+        payloads = (match.payload for match in matches)
+        console.log """
+        Dispatching found more than one candidate, so we're using the first.
+        Match payloads:
+        """
+        for payload in payloads
+          console.log(payload)
       # first match, obviously. compile_matches is a good place
       # to sort the matches based on whatever criteria we decide
       # to use.


Variable mode

Variable mode

--- SingularityUI/app/components/aggregateTail/Contents.cjsx
+++ SingularityUI/app/components/aggregateTail/Contents.cjsx
@@ -56,7 +56,7 @@
     else if $(node).scrollTop() is 0
       @stopTailingPoll()
       @setState
-        isLoading: true
+        isLoading: true
       @props.fetchPrevious(=>
         @setState
           isLoading: false
@@ -131,7 +131,7 @@
           itemRenderer={@lineRenderer}
           itemSizeGetter={@getLineHeight}
           length={@state.linesToRender.length}
-          type="uniform">
+          type="variable">
         </ReactList>
       </div>
       <Loader isVisable={@state.isLoading} text={@state.loadingText} />


Made unserializeQueryProps function.

Made unserializeQueryProps function.

--- db.coffee
+++ db.coffee
@@ -14,6 +14,12 @@
 getQueryProps = (query) ->
 	props = [ 'key', 'startkey', 'endkey', 'descending' ]
 	utils.getProps query, props
+
+unserializeQueryProps = (query) ->
+	t.seq(
+		getQueryProps query
+		utils.mapValues utils.applyIfString JSON.parse
+	)

 getDocFromRow = (row) ->
 	row.doc
@@ -43,10 +49,7 @@
 get = (arg1) ->
 	view = if arguments.length == 2 then arg1 else ''
 	if view
-		query = t.seq(
-			getQueryProps arguments[arguments.length - 1]
-			utils.mapValues utils.applyIfString JSON.parse
-		)
+		query = unserializeQueryProps arguments[arguments.length - 1]
 	else
 		query = getQueryProps arguments[arguments.length - 1]
 	query.include_docs = true


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/camera.coffee
+++ src/camera.coffee
@@ -39,6 +39,7 @@

     else if objectCenter.x < centerRect.left

+

     I.scroll = Point(


Add warning about carefully deploying surveys

And not breaking the apps unnecessarily.

--- app/models/subject.coffee
+++ app/models/subject.coffee
@@ -65,6 +65,17 @@

   @url: (params) -> @withParams "/projects/galaxy_zoo/groups/#{ params.surveyId }/subjects", limit: params.limit

+  # NOTE: Before changing the active surveys on the live website,
+  # please give a few days notice to the maintainers of the Android and iPhone apps.
+  # See https://github.com/murraycu/android-galaxyzoo/ and https://github.com/murraycu/ios-galaxyzoo/
+  #
+  # Ideally, any changes to use a new survey would first happen in a branch before being merged to master.
+  # android-galaxyzoo has several tests that can find user-visible errors in the decision trees and their associated
+  # icons and example images. These errors are easy to cause by making simple typos.
+  #
+  # Please also do not immediately disable the older survey on the server. Doing so means that the apps will suddenly
+  # stop working until a user of the app informs the developer and the developer then has time to fix the error.
+  # For iPhone apps there will also be a delay until the updated App is approved.
   @randomSurveyId: ->
     return @::surveys.decals_dr2.id
     n = Math.random()


prevent unexpected deleting

prevent unexpected deleting

--- app/scripts/editor.coffee
+++ app/scripts/editor.coffee
@@ -141,7 +141,7 @@
 				@status.cmd = true
 				$('.cmd').removeClass('hidden')
 			when 8
-				if $('#editor').html().match /^<(h1|h2|p|code) name=".{4}">
<\/(h1|h2|p|code)>
<\/p>/
+				if $('#editor').html().match /^<(h1|h2|p|pre|code) name=".{4}">
<\/(h1|h2|p|pre|code)>/
 					e.preventDefault()
 					e.stopPropagation()


- Increased reliability of pages capturing their active status

--- Vimtastic.safariextension/coffee/global/Vimtastic.coffee
+++ Vimtastic.safariextension/coffee/global/Vimtastic.coffee
@@ -7,16 +7,23 @@
 		@browser = new BrowserManipulation
 		@activeTab = @browser.activeTab().tab
 		safari.application.addEventListener "message", @routeMessage, yes
+		safari.application.addEventListener "open", @activate, yes
+		safari.application.addEventListener "navigate", @activate, yes
 		safari.application.addEventListener "activate", @activate, yes
 		safari.application.addEventListener "deactivate", @deactivate, yes

 	activate: (e) ->
+		console.log "activated"
 		if e.target.page?
 			e.target.page.dispatchMessage "setActive", yes
+		else
+			e.target.activeTab.page.dispatchMessage "setActive", yes

 	deactivate: (e) ->
 		if e.target.page?
 			e.target.page.dispatchMessage "setActive", no
+		else
+			e.target.activeTab.page.dispatchMessage "setActive", no

 	routeMessage: (e) =>
 		switch e.name


:lipstick: inline method

:lipstick: inline method

--- src/keymap.coffee
+++ src/keymap.coffee
@@ -39,7 +39,16 @@
   #   keystroke patterns to commands.
   addKeyBindings: (source, keyBindingsBySelector) ->
     for selector, keyBindings of keyBindingsBySelector
-      @addKeyBindingsForSelector(source, selector, keyBindings)
+      # Verify selector is valid before registering any bindings
+      try
+        document.body.webkitMatchesSelector(selector.replace(/!important/g, ''))
+      catch e
+        console.warn("Encountered an invalid selector adding key bindings from '#{source}': '#{selector}'")
+        return
+
+      for keystroke, command of keyBindings
+        keyBinding = new KeyBinding(source, command, keystroke, selector)
+        @keyBindings.push(keyBinding)

   # Public: Load the key bindings from the given path.
   #
@@ -88,18 +97,6 @@
         @keystrokes = []
         return if @dispatchCommandEvent(event, target, candidateBindings[0].command)
       target = target.parentElement
-
-  addKeyBindingsForSelector: (source, selector, keyBindings) ->
-    # Verify selector is valid before registering any bindings
-    try
-      document.body.webkitMatchesSelector(selector.replace(/!important/g, ''))
-    catch e
-      console.warn("Encountered an invalid selector adding key bindings from '#{source}': '#{selector}'")
-      return
-
-    for keystroke, command of keyBindings
-      keyBinding = new KeyBinding(source, command, keystroke, selector)
-      @keyBindings.push(keyBinding)

   # Public: Get the key bindings for a given command and optional target.
   #
@@ -208,7 +205,9 @@
   # Deprecated: Use {::addKeyBindings} with a map from selectors to key
   # bindings.
   bindKeys: (source, selector, keyBindings) ->
-    @addKeyBindingsForSelector(source, selector, keyBindings)
+    keyBindingsBySelector = {}
+    keyBindingsBySelector[selector] = keyBindings
+    @addKeyBindings(source, keyBindingsBySelector)

   # Deprecated: Use {::findKeyBindings} with the 'command' param.
   keyBindingsForCommand: (command) ->


Throw an error if can't load a module in base.coffee

--- bokehjs/src/coffee/common/base.coffee
+++ bokehjs/src/coffee/common/base.coffee
@@ -168,7 +168,12 @@

     if not mod_cache[modulename]?
       console.log("calling require", modulename)
-      mod_cache[modulename] = require(modulename)
+      mod = require(modulename)
+
+      if mod?
+          mod_cache[modulename] = mod
+      else
+          throw Error("improperly implemented collection: #{modulename}")

     return mod_cache[modulename].Collection
   Collections.register = (name, collection) ->


remove items from current folder

remove items from current folder

--- static/coffee/controllers.coffee
+++ static/coffee/controllers.coffee
@@ -270,12 +270,9 @@
               # new item so we add it to the top
               $scope.items.unshift(item)

-      # remove the archived items
-      if $scope.activeSearchRefresh.folder != 'archived'
-          $scope.items = (item for item in $scope.items when item.archived == false)
-
-      if $scope.activeSearchRefresh.folder != 'flagged'
-          $scope.items = (item for item in $scope.items when item.flagged == false)
+      # items removed from current folder
+      filter = $scope.getItemFilter()
+      $scope.items = (item for item in $scope.items when filter(item))

     ).catch((error) ->
       $scope.pollBusy = false


build fix

build fix

--- modules/blog.coffee
+++ modules/blog.coffee
@@ -5,7 +5,7 @@
 			@blog = settings.mongoose.model 'blog'
 			@post = settings.mongoose.model 'post'
 			@helper = (require __dirname + '/helper')()
-			@category = (requireo __dirname + '/category')(settings)
+			@category = (require __dirname + '/category')(settings)
 			@media = (require __dirname + '/media')(settings)
 			@map = settings.mongoose.model 'map'


make `<box/>` command accept `width`, `border` attributes

--- src/tex-writer.coffee
+++ src/tex-writer.coffee
@@ -660,10 +660,9 @@
     if select event, '(', 'box'
       [ type, name, Q, meta, ] = event
       send stamp event
-      if Q.frame?
-        send [ 'tex', "\\framebox{", ]
-      else
-        send [ 'tex', "\\makebox{", ]
+      command = if Q.border? then 'framebox' else 'makebox'
+      if Q.width? then  send [ 'tex', "\\#{command}[#{Q.width}]{", ]
+      else              send [ 'tex', "\\#{command}{", ]
     #.......................................................................................................
     else if select event, ')', 'box'
       send stamp event


#241 typo

#241 typo

--- spec/text-object-spec.coffee
+++ spec/text-object-spec.coffee
@@ -1428,7 +1428,7 @@
             4 abc
             """
     describe 'as operator target', ->
-      it 'delete next occurence of last sarch pattern', ->
+      it 'delete next occurence of last search pattern', ->
         ensure 'dgn',
           cursor: [1, 2]
           mode: 'normal'
@@ -1459,7 +1459,7 @@
             3 xxx_
             4 \n
             """.replace('_', ' ') # To prevent trailing space remved on save.
-      it 'change next occurence of last sarch pattern', ->
+      it 'change next occurence of last search pattern', ->
         ensure 'cgn',
           cursor: [1, 2]
           mode: 'insert'


Don't do anything special when constructing the LineTool

We don't know what sizes may be available, if the application is only
using core.

--- src/tools/Line.coffee
+++ src/tools/Line.coffee
@@ -7,7 +7,6 @@
   name: 'Line'
   iconName: 'line'

-  constructor: -> @strokeWidth = 5
   optionsStyle: 'line-options-and-stroke-width'

   begin: (x, y, lc) ->


Seal Command Help

Seal Command Help

--- modules/help.coffee
+++ modules/help.coffee
@@ -27,6 +27,7 @@
     #{@prefix}filters              - Shows information about filters
     #{@prefix}stats                - Technical stuff about the bot
     #{@prefix}ping                 - Pong!
+    #{@prefix}seal                 - Sends seal pictures

     Bot Commanders Only:
     #{@prefix}volume  <vol>        - Sets volume of the bot


Removed some silly extra key bindings.

Removed some silly extra key bindings.

The actual binding are in the menu items.

--- src/ui/hotkeys.coffee
+++ src/ui/hotkeys.coffee
@@ -98,8 +98,6 @@

       up:
         'space': -> @switchToLastTool()
-        '+': -> @refreshAfterZoom()
-        '-': -> @refreshAfterZoom()

   use: (set) ->


refactor for flexibility wip

refactor for flexibility wip

--- src/app/storyline/story.coffee
+++ src/app/storyline/story.coffee
@@ -27,14 +27,30 @@

 storyline.controller 'StoryCtrl', StoryCtrl

-class StoryScreen
-  constructor: (@type, @stage, @text, @options) ->
+class CutScene
+  constructor: (@stage, @screens) ->
+
+class Screen
+  constructor: (@style, @dialogs, @options) ->
+  add_dialog: (@dialog) ->
+    @content.push @dialog
+
+class Dialog
+  constructor: (@type, @content, @options) ->

 storyline.service "StoryService", ->

   check_points = {
-    "1_start": [new StoryScreen("modal", "round_start", "You're nervous as you boot up the test. What if you confuse Teen Wolf for Supernatural? You'd be mortified.")],
-    "1_end": [new StoryScreen("modal", "round_end", "You sigh with relief as you successfully complete your first level. You've taken the first step towards Earth.")]
+    "1_start": new CutScene("round_start", [
+      new Screen("modal", [
+        new Dialog("text", "You're nervous as you boot up the test. What if you confuse Teen Wolf for Supernatural? You'd be mortified.")
+        ])
+      ]),
+    "1_end": new CutScene("round_end", [
+      new Screen("modal", [
+        new Dialog("text", "You sigh with relief as you successfully complete your first level. You've taken the first step towards Earth.")
+        ])
+      ])
   }
   random_chapters = {
     "start": [


add: comments

add: comments

--- jquery.store.coffee
+++ jquery.store.coffee
@@ -1,4 +1,6 @@
 # jQuery Store
+#
+# jQuery Store can store almost all type of objects.

 (($) ->
   $.fn.extend


Parsing 3-digit hexadecimal colors fixed


Update atom editor config

Update atom editor config

--- config.cson
+++ config.cson
@@ -3,13 +3,10 @@
     enabled: true
   core:
     audioBeep: false
+    closeDeletedFileTabs: true
     excludeVcsIgnoredPaths: false
     packagesWithKeymapsDisabled: []
     telemetryConsent: "limited"
-    themes: [
-      "one-light-ui"
-      "one-light-syntax"
-    ]
   "custom-title":
     template: "<%= fileName %><% if (projectPath) { %> - <%= projectPath %><% if (gitHead) { %> [<%= gitHead %>]<% } %><% } %>"
   editor:


Marionette API change.

Marionette API change.


revert the < 1s change to as_duration

revert the < 1s change to as_duration

--- js/libs/time.coffee
+++ js/libs/time.coffee
@@ -47,7 +47,5 @@
       "#{minutes}m"
     else if minutes > 0
       "#{minutes}m #{seconds % 60}s"
-    else if duration > 1000
+    else
       "#{seconds}s"
-    else
-      "< 1s"


Fix multibyte bug

Fix multibyte bug

--- src/chunked-line-reader.coffee
+++ src/chunked-line-reader.coffee
@@ -1,6 +1,7 @@
 fs = require("fs")
 isBinaryFile = require("isbinaryfile")
 {Readable} = require 'stream'
+{StringDecoder} = require 'string_decoder'

 lastIndexOf = (buffer, length, char) ->
   i = length
@@ -47,6 +48,7 @@
       @constructor.chunkedBuffer ?= new Buffer(chunkSize)
       chunkedBuffer = @constructor.chunkedBuffer
       bytesRead = fs.readSync(fd, chunkedBuffer, 0, chunkSize, 0)
+      decoder = new StringDecoder('utf8')

       while bytesRead
         # Scary looking. Uses very few new objects
@@ -55,15 +57,15 @@

         if index < 0
           # no newlines here, the whole thing is a remainder
-          newRemainder = chunkedBuffer.toString("utf8", 0, bytesRead)
+          newRemainder = decoder.write(chunkedBuffer.slice(0, bytesRead))
           str = null
         else if index > -1 and index == bytesRead - 1
           # the last char is a newline
           newRemainder = ''
-          str = chunkedBuffer.toString("utf8", 0, bytesRead)
+          str = decoder.write(chunkedBuffer.slice(0, bytesRead))
         else
-          newRemainder = chunkedBuffer.toString("utf8", index+1, bytesRead)
-          str = chunkedBuffer.toString("utf8", 0, index+1)
+          str = decoder.write(chunkedBuffer.slice(0, index+1))
+          newRemainder = decoder.write(chunkedBuffer.slice(index+1, bytesRead))

         if str
           str = remainder + str if remainder


Update Esperanto translation (#197)

Update Esperanto translation (#197)

--- src/coffee/translations.coffee
+++ src/coffee/translations.coffee
@@ -122,15 +122,16 @@
         app: "Aplikaĵo"
         cloud: "Nubo"
         other_client: "Alia aplikaĵo"
+        let_the_device_decide: "Aŭtomata propono"
       finish_panel:
         handing_over_to: "Transdonanta al %{client}"
         something_went_wrong: "Ĉu io misfunkciis?"
         try_again: "Reprovi"
-        install: "Viziti la retejon de %{client}"
+        install: "Instali %{client}'n"
         register_an_account: "Registriĝi ĉe "
         please_copy_url: "Bonvolu kopii la suban URLn kaj aldoni ĝin al via podkasta aplikaĵo aŭ RSS-legilo."
-        copy_button_text: "Copy URL"
-        copy_success: "URL copied to clipboard"
+        copy_button_text: "Kopii URLn"
+        copy_success: "URL kopiite"
         or_install: "aŭ instali la aplikaĵon"

     fi:


Update perf test

Update perf test

--- extras/Perf.framer/app.coffee
+++ extras/Perf.framer/app.coffee
@@ -19,7 +19,6 @@

 	totalTime: ->
 		@_time - @_start
-

 	droppedFrames: ->
 		_.filter @_frames, (t) -> t > (1 / 60) * 1.1
@@ -53,15 +52,17 @@
 		width: options.width
 		height: options.height
 		backgroundColor: "rgba(0, 0, 0, .1)"
+		clip: true

 	root.center()

 	layers = for i in [0..n]

 		layer = new Layer
+			width: 100, height: 100,
 			x: Math.random() * options.width - (.5 * 100)
 			y: Math.random() * options.height - (.5 * 100)
-			backgroundColor: Color.random(.3)
+			backgroundColor: Utils.randomColor(.3)
 			superLayer: root

 	fps = new FPS


user: fix defaultUser logic

user: fix defaultUser logic

--- models/user.coffee
+++ models/user.coffee
@@ -22,7 +22,7 @@
   return c is 0

 defaultUser = (user) ->
-  id = uuid.v4()
+  id = user.id or uuid.v4()
   _.defaults user, {
     id: id
     joinDay: Math.floor(Date.now() / MS_IN_DAY)


Undo changes on box

Undo changes on box

--- app/assets/javascripts/oxalis/geometries/skeleton.coffee
+++ app/assets/javascripts/oxalis/geometries/skeleton.coffee
@@ -147,13 +147,6 @@
       @waypointAnimation.onUpdate ->
         @flycam.setPosition [@globalPosX, @globalPosY, @globalPosZ]
       @waypointAnimation.start()
-      #@waypointAnimation = new TWEEN.Tween({ globalPosX: curGlobalPos[0], globalPosY: curGlobalPos[1], globalPosZ: curGlobalPos[2], flycam: @flycam})
-      #@waypointAnimation.to({globalPosX: position[0], globalPosY: position[1], globalPosZ: position[2]}, 200)
-      #@waypointAnimation.onUpdate ->
-      #  @flycam.setPosition [@globalPosX, @globalPosY, @globalPosZ]
-      #@waypointAnimation.start()
-
-      @setActiveNode()

     @flycam.update()


OX-607 also enabled setRendererSize for arbitrary mode to avoid rendering issues/bugs

--- app/assets/javascripts/oxalis/view/arbitrary_view.coffee
+++ app/assets/javascripts/oxalis/view/arbitrary_view.coffee
@@ -60,8 +60,6 @@
       $("#arbitrary-info-canvas").show()

       @resize()
-      #render hack to avoid flickering
-      @renderer.setSize(constants.WIDTH, constants.WIDTH)
       # start the rendering loop
       @animate()
       # Dont forget to handle window resizing!
@@ -131,12 +129,24 @@
     return

+  # throttle resize to avoid annoying flickering
+  resizeThrottled : ->
+
+    @resizeThrottled = _.throttle(
+      => @resize()
+      500
+    )
+    @resizeThrottled()
+
+
   # Call this after the canvas was resized to fix the viewport
   # Needs to be bound
   resize : =>

     @width  = @container.width()
     @height = @container.height()
+
+    @renderer.setSize(@width, @height)

     @camera.aspect = @width / @height
     @camera.updateProjectionMatrix()
@@ -153,7 +163,7 @@
       @container.width(@width)
       @container.height(@height)

-      @resize()
+      @resizeThrottled()

   setRouteClippingDistance : (value) =>


Remove unnecessary duplicate function findAnyStartPair in favor of findMatchingStartPair

--- lib/bracket-matcher-view.coffee
+++ lib/bracket-matcher-view.coffee
@@ -83,22 +83,6 @@
         stop() if unpairedCount < 0
     startPairPosition

-  findAnyStartPair: (endPairPosition) ->
-    scanRange = new Range([0, 0], endPairPosition)
-    startPair = '{'
-    endPair = '}'
-    regex = new RegExp("[#{_.escapeRegExp(startPair + endPair)}]", 'g')
-    startPosition = null
-    unpairedCount = 0
-    @editor.backwardsScanInBufferRange regex, scanRange, ({match, range, stop}) =>
-      if match[0] is endPair
-        unpairedCount++
-      else if match[0] is startPair
-        unpairedCount--
-        startPosition = range.start
-        stop() if unpairedCount < 0
-    startPosition
-
   moveHighlightView: (view, bufferPosition, pixelPosition) ->
     view.bufferPosition = bufferPosition
     [element] = view
@@ -149,6 +133,6 @@
     return unless @editorView.underlayer.isVisible()
     position = @editor.getCursorBufferPosition()
     return unless position
-    matchPosition = @findAnyStartPair(position)
+    matchPosition = @findMatchingStartPair(position, '{', '}')
     if matchPosition
       @editor.setCursorBufferPosition(matchPosition)


this multi-line string was messing-up with my coffee theme

--- web/app.coffee
+++ web/app.coffee
@@ -114,8 +114,7 @@
         if req.method is 'GET' or req.method is 'HEAD'
           next()
         else
-          heck.handler req, res, "
-Route '#{req.url}' not found, the '#{req.method}' method not allowed further.",
+          heck.handler req, res, "Route '#{req.url}' not found, the '#{req.method}' method not allowed further.",
             405

   # Cloud9's vfs for static files


update acceptance tests settings to 2017 image

--- test/acceptance/scripts/settings.test.coffee
+++ test/acceptance/scripts/settings.test.coffee
@@ -23,9 +23,9 @@
 		commandRunner: "docker-runner-sharelatex"
 		latexmkCommandPrefix: ["/usr/bin/time", "-v"]         # on Linux
 		docker:
-			image: "texlive-full:2016.1-opt"
+			image: "texlive-full:2017.1-opt"
 			env:
-				PATH: "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/texlive/2016/bin/x86_64-linux/"
+				PATH: "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/texlive/2017/bin/x86_64-linux/"
 				HOME: "/tmp"
 			modem:
 				socketPath: false


Add issue link to dropdown

Add issue link to dropdown

--- src/app/package-config-view.coffee
+++ src/app/package-config-view.coffee
@@ -50,11 +50,16 @@
     unless homepage
       repoUrl = (@pack.repository?.url ? '').replace(/.git$/, '')
       homepage = repoUrl if require('url').parse(repoUrl).host is 'github.com'
-
     if homepage
       @dropdown.append $$ ->
         @li =>
-          @a "Visit Homepage", href: homepage
+          @a "Visit homepage", href: homepage
+
+    if issues = @pack.bugs?.url
+      @dropdown.append $$ ->
+        @li =>
+          @a "Report issue", href: issues
+
     @dropdown.on 'click', => @dropdown.hide()

     @updateInstallState()


Sidebar: Create machine box views.

Sidebar: Create machine box views.

--- client/Social/Activity/sidebar/sidebarmachinelist.coffee
+++ client/Social/Activity/sidebar/sidebarmachinelist.coffee
@@ -24,3 +24,6 @@
           @emit 'ListHeaderPlusIconClicked'

     @addSubView @header
+
+    for machineData in data
+      @addSubView new SidebarMachineBox {}, machineData


Client: Activity: Feed: Moved ChatListItem modals to MessageItemMenu component

--- client/activity/lib/components/chatlistitem/index.coffee
+++ client/activity/lib/components/chatlistitem/index.coffee
@@ -1,38 +1,24 @@
 kd                      = require 'kd'
 React                   = require 'kd-react'
 ReactDOM                = require 'react-dom'
-remote                  = require('app/remote').getInstance()
 Avatar                  = require 'app/components/profile/avatar'
 immutable               = require 'immutable'
 MessageBody             = require 'activity/components/common/messagebody'
 ProfileText             = require 'app/components/profile/profiletext'
 ProfileLinkContainer    = require 'app/components/profile/profilelinkcontainer'
-ButtonWithMenu          = require 'app/components/buttonwithmenu'
-ActivityPromptModal     = require 'app/components/activitypromptmodal'
-MarkUserAsTrollModal    = require 'app/components/markuserastrollmodal'
-BlockUserModal          = require 'app/components/blockusermodal'
 ActivityLikeLink        = require 'activity/components/chatlistitem/activitylikelink'
 MessageTime             = require 'activity/components/chatlistitem/messagetime'
-keycode                 = require 'keycode'
-AppFlux                 = require 'app/flux'
 ActivityFlux            = require 'activity/flux'
 classnames              = require 'classnames'
-Portal                  = require 'react-portal'
-whoami                  = require 'app/util/whoami'
-checkFlag               = require 'app/util/checkFlag'
-impersonate             = require 'app/util/impersonate'
-getMessageOwner         = require 'app/util/getMessageOwner'
-showErrorNotification   = require 'app/util/showErrorNotification'
-showNotification        = require 'app/util/showNotification'
 ImmutableRenderMixin    = require 'react-immutable-render-mixin'
 EmbedBox                = require 'activity/components/embedbox'
-KeyboardKeys            = require 'app/util/keyboardKeys'
 ChatInputEmbedExtractor = require 'activity/components/chatinputembedextractor'
 ChannelToken            = require 'activity/components/chatinputwidget/tokens/channeltoken'
 EmojiToken              = require 'activity/components/chatinputwidget/tokens/emojitoken'
 MentionToken            = require 'activity/components/chatinputwidget/tokens/mentiontoken'
 Encoder                 = require 'htmlencode'
 MessageLink             = require 'activity/components/messagelink'
+MessageItemMenu         = require 'activity/components/messageitemmenu'

 module.exports = class ChatListItem extends React.Component

@@ -65,9 +51,6 @@
       isMarkUserAsTrollModalVisible : @props.isMarkUserAsTrollModalVisible

-  componentDidMount: ->
-
-    @getAccountInfo()

   componentDidUpdate: (prevProps, prevState) ->
@@ -76,18 +59,6 @@
     wasInEditMode = prevProps.message.get '__isEditing'

     @refs.editInput.focus()  if isInEditMode and not wasInEditMode
-
-
-  getAccountInfo: ->
-
-    { message } = @props
-    message = message.toJS()
-
-    if message.account._id
-      remote.cacheable "JAccount", message.account._id, (err, account)=>
-        return @setState account: account  if account
-    else if message.bongo_.constructorName is 'JAccount'
-      return @setState account: message  if account

   isEditedMessage: ->
@@ -104,141 +75,6 @@
     className         : classnames
       'ChatItem'      : yes
       'is-selected'   : @props.isSelected
-
-  getMenuItems: ->
-
-    if checkFlag('super-admin')
-    then @getAdminMenuItems()
-    else @getDefaultMenuItems()
-
-
-  getDefaultMenuItems: ->
-
-    return [
-      {title: 'Edit Post'   , key: 'editpost'             , onClick: @bound 'editPost'}
-      {title: 'Delete Post' , key: 'showdeletepostprompt' , onClick: @bound 'showDeletePostPromptModal'}
-    ]
-
-
-  getAdminMenuItems: ->
-
-    { message } = @props
-    markUserMenuItem = {title: 'Mark User as Troll', key: 'markuserastroll', onClick: @bound 'showMarkUserAsTrollPromptModal'}
-
-    getMessageOwner message.toJS(), (err, owner) =>
-
-      return showErrorNotification err  if err
-
-      if owner.isExempt
-        markUserMenuItem = {title: 'Unmark User as Troll', key: 'unmarkuserastroll', onClick: @bound 'unMarkUserAsTroll'}
-
-    adminMenuItems = [
-      markUserMenuItem
-      {
-        title   : 'Block User'
-        key     : 'blockuser'
-        onClick : @bound 'showBlockUserPromptModal'
-      }
-      {
-        title   : 'Impersonate User'
-        key     : 'impersonateuser'
-        onClick : @bound 'impersonateUser'
-      }
-    ]
-
-    return @getDefaultMenuItems().concat adminMenuItems
-
-
-  getDeleteItemModalProps: ->
-
-    title              : "Delete post"
-    body               : "Are you sure you want to delete this post?"
-    buttonConfirmTitle : "DELETE"
-    className          : "Modal-DeleteItemPrompt"
-    onConfirm          : @bound "deletePostButtonHandler"
-    onAbort            : @bound "closeDeletePostModal"
-    onClose            : @bound "closeDeletePostModal"
-
-
-  getMarkUserAsTrollModalProps: ->
-
-    account            : @state.account
-    title              : "MARK USER AS TROLL"
-    className          : "MarkUserAsTrollModal"
-    onAbort            : @bound "closeMarkUserAsTrollModal"
-    onClose            : @bound "closeMarkUserAsTrollModal"
-    buttonConfirmTitle : "YES, THIS USER IS DEFINITELY A TROLL"
-
-
-  getBlockUserModalProps: ->
-
-    account            : @state.account
-    buttonConfirmTitle : "BLOCK USER"
-    className          : "BlockUserModal"
-    onAbort            : @bound "closeBlockUserPromptModal"
-    onClose            : @bound "closeBlockUserPromptModal"
-
-
-  deletePostButtonHandler: (event) ->
-
-    kd.utils.stopDOMEvent event
-    ActivityFlux.actions.message.removeMessage @props.message.get('id')
-    @closeDeletePostModal()
-
-
-  closeDeletePostModal: (event) ->
-
-    kd.utils.stopDOMEvent event
-    @setState isDeleting: no
-
-
-  editPost: ->
-
-    messageId = @props.message.get '_id'
-
-    ActivityFlux.actions.message.setMessageEditMode messageId, @props.channelId
-
-
-  showDeletePostPromptModal: ->
-
-    @setState isDeleting: yes
-
-
-  showMarkUserAsTrollPromptModal: ->
-
-    @setState isMarkUserAsTrollModalVisible: yes
-
-
-  closeMarkUserAsTrollModal: (event) ->
-
-    kd.utils.stopDOMEvent event
-    @setState isMarkUserAsTrollModalVisible: no
-
-
-  closeBlockUserPromptModal: (event) ->
-
-    kd.utils.stopDOMEvent event
-    @setState isBlockUserModalVisible: no
-
-
-  unMarkUserAsTroll: (event) ->
-
-    kd.utils.stopDOMEvent event
-    AppFlux.actions.user.unmarkUserAsTroll @state.account
-    @closeMarkUserAsTrollModal()
-
-
-  showBlockUserPromptModal: ->
-
-    @setState isBlockUserModalVisible: yes
-
-
-  impersonateUser: (event) ->
-
-    kd.utils.stopDOMEvent event
-    { message } = @props
-
-    AppFlux.actions.user.impersonateUser message.toJS()

   updateMessage: ->
@@ -317,9 +153,7 @@

     return null  unless @props.showItemMenu

-    { message } = @props
-    if (message.get('accountId') is whoami().socialApiId) or checkFlag('super-admin')
-      <ButtonWithMenu items={@getMenuItems()} />
+    <MessageItemMenu message={@props.message}/>

   renderEmbedBox: ->
@@ -359,11 +193,6 @@
         {@renderEditMode()}
         {@renderEmbedBox()}
         {@renderChatItemMenu()}
-        <ActivityPromptModal {...@getDeleteItemModalProps()} isOpen={@state.isDeleting}>
-          Are you sure you want to delete this post?
-        </ActivityPromptModal>
-        <MarkUserAsTrollModal {...@getMarkUserAsTrollModalProps()} isOpen={@state.isMarkUserAsTrollModalVisible} />
-        <BlockUserModal {...@getBlockUserModalProps()} isOpen={@state.isBlockUserModalVisible} />
       </div>
     </div>


Client: Activity: Added handleSetAllMessagesLoaded and handleUnsetAllMessagesLoaded methods to set/unset reachedFirstMessage channel flag

--- client/activity/lib/flux/stores/channelflagsstore.coffee
+++ client/activity/lib/flux/stores/channelflagsstore.coffee
@@ -18,7 +18,8 @@
     @on actions.CREATE_MESSAGE_BEGIN, @handleCreateMessageBegin
     @on actions.CREATE_MESSAGE_SUCCESS, @handleCreateMessageEnd
     @on actions.CREATE_MESSAGE_FAIL, @handleCreateMessageEnd
-
+    @on actions.SET_ALL_MESSAGES_LOADED, @handleSetAllMessagesLoaded
+    @on actions.UNSET_ALL_MESSAGES_LOADED, @handleUnsetAllMessagesLoaded

   handleLoadMessagesBegin: (channelFlags, { channelId }) ->

@@ -44,6 +45,18 @@
     return channelFlags.setIn [channelId, 'isMessageBeingSubmitted'], no

+  handleSetAllMessagesLoaded: (channelFlags, { channelId }) ->
+
+    channelFlags = helper.ensureChannelMap channelFlags, channelId
+    return channelFlags.setIn [channelId, 'reachedFirstMessage'], yes
+
+
+  handleUnsetAllMessagesLoaded: (channelFlags, { channelId }) ->
+
+    channelFlags = helper.ensureChannelMap channelFlags, channelId
+    return channelFlags.setIn [channelId, 'reachedFirstMessage'], no
+
+
 helper =

   ensureChannelMap: (channelFlags, channelId) ->


Accept the right file types for subject uploading

--- app/pages/lab/subject-set.cjsx
+++ app/pages/lab/subject-set.cjsx
@@ -45,7 +45,7 @@

-        <UploadDropTarget onSelect={@handleFileSelection}>
+        <UploadDropTarget accept="text/csv, text/tab-separated-values, image/*" onSelect={@handleFileSelection}>
           Drag-and-drop manifests and subject images here.

           Manifests must be .csv or .tsv. The first row should define metadata headers. All other rows should include at least one reference to an image filename in the same directory as the manifest.

           Subject images can be any of: {{ext}{' '} for ext in VALID_SUBJECT_EXTENSIONS}.


Save and render the result count when it is first created

This fixes the issue where the user would navigate to the query workspace first and then to the results workspace leaving the count empty. The reason for this was that the ResultCount view does not exist when the query workspace is hit so the trigger on change:objectcount event was not received by ResultCount since it didn't exist yet. This handles that case by showing the count when it is created and storing the count when the trigger occurs so any possible navigation path should always show the count now.

--- src/coffee/cilantro/ui/workflows/results.coffee
+++ src/coffee/cilantro/ui/workflows/results.coffee
@@ -33,8 +33,17 @@
         modelEvents:
             'change:objectcount': 'renderCount'

+        initialize: ->
+            super
+
+            @count = @model.objectCount if @model.objectCount? or ''
+
+        onRender: ->
+            @renderCount(@model, @count)
+
         renderCount: (model, count, options) ->
-            numbers.renderCount(@ui.count, count)
+            @count = count
+            numbers.renderCount(@ui.count, @count)
             @ui.label.text('records')


Write atom.sh to atom in bin folder

Write atom.sh to atom in bin folder

--- src/browser/squirrel-update.coffee
+++ src/browser/squirrel-update.coffee
@@ -115,6 +115,7 @@
     relativeAtomPath = path.relative(binFolder, path.join(appFolder, 'resources', 'cli', 'atom.cmd'))
     atomCommand = "@echo off\r\n\"%~dp0\\#{relativeAtomPath}\" %*"

+    atomShCommandPath = path.join(binFolder, 'atom')
     relativeAtomShPath = path.relative(binFolder, path.join(appFolder, 'resources', 'cli', 'atom.sh'))
     atomShCommand = "#!/bin/sh\r\n\"$0\\#{relativeAtomPath}\" \"$@\""


Fix button interaction logic: disable hoverstate on click.

--- core/app/backbone/views/tour/tour_users_list_view.coffee
+++ core/app/backbone/views/tour/tour_users_list_view.coffee
@@ -1,11 +1,6 @@
 class TourUserView extends ActionButtonView
   template: 'tour/interesting_user'
   className: 'tour-interesting-user'
-  templateHelpers: =>
-    disabled_label: Factlink.Global.t.follow_user.capitalize()
-    disable_label:  Factlink.Global.t.unfollow.capitalize()
-    enabled_label:  Factlink.Global.t.following.capitalize()
-
   templateHelpers: =>
     disabled_label: Factlink.Global.t.follow_user.capitalize()
     disable_label:  Factlink.Global.t.unfollow.capitalize()
@@ -30,10 +25,12 @@
   primaryAction: ->
     @model.follow()
     # TODO: favourite
+    @$el.removeClass 'hover'
     @updateButton()

   secondaryAction: ->
     @model.unfollow()
+    @$el.removeClass 'hover'
     @updateButton()

 class window.TourUsersListView extends Backbone.Marionette.CollectionView


DEMO: Buttons: add some more examples of flat + small and bordered buttons.


person_ref added for person api.

person_ref added for person api.

--- src/core/javascripts/controllers/base.js.coffee
+++ src/core/javascripts/controllers/base.js.coffee
@@ -463,6 +463,12 @@
         $scope.bb.default_setup_promises.push(person)
         person.then (res) =>
           $scope.bb.item_defaults.person = new BBModel.Person(res)
+
+      if $scope.bb.item_defaults.person_ref
+        person = halClient.$get($scope.bb.api_url + '/api/v1/' + company_id + '/people/find_by_ref/' + $scope.bb.item_defaults.person_ref)
+        $scope.bb.default_setup_promises.push(person)
+        person.then (res) =>
+        $scope.bb.item_defaults.person = new BBModel.Person(res)

       if $scope.bb.item_defaults.service
         service = halClient.$get($scope.bb.api_url + '/api/v1/' + company_id + '/services/' + $scope.bb.item_defaults.service )


Updated item conflict handling so that SDK will first look for date/event routes to return to before otherwise going back to the previous step [YBS-195]

--- src/core/javascripts/controllers/base.js.coffee
+++ src/core/javascripts/controllers/base.js.coffee
@@ -151,6 +151,7 @@
     Basket: 10
     Checkout: 11
     Slot: 12
+    Event: 13
   $scope.Route = $rootScope.Route

@@ -616,6 +617,7 @@

     else if ($scope.bb.company.$has('event_groups') && !$scope.bb.current_item.event_group && !$scope.bb.current_item.service && !$scope.bb.current_item.product && !$scope.bb.current_item.deal) or
             ($scope.bb.company.$has('events') && $scope.bb.current_item.event_group && !$scope.bb.current_item.event? && !$scope.bb.current_item.product && !$scope.bb.current_item.deal)
+      return if $scope.setPageRoute($rootScope.Route.Event)
       return $scope.showPage('event_list')
     else if ($scope.bb.company.$has('events') && $scope.bb.current_item.event && !$scope.bb.current_item.num_book && (!$scope.bb.current_item.tickets || !$scope.bb.current_item.tickets.qty) && !$scope.bb.current_item.product && !$scope.bb.current_item.deal)
       return $scope.showPage('event')
@@ -724,6 +726,7 @@
         add_defer.resolve(basket)
     , (err) ->
       add_defer.reject(err)
+      # handle item conflict
       if err.status == 409
         # clear the currently cached time date
         halClient.clearCache("time_data")
@@ -738,7 +741,13 @@
               $modalInstance.close()
         error_modal.result.finally () ->
           if $scope.bb.nextSteps
-            $scope.loadPreviousStep()
+            # either go back to the Date/Event routes or load the previous step
+            if $scope.setPageRoute($rootScope.Route.Date)
+              # already routed
+            else if $scope.setPageRoute($rootScope.Route.Event)
+              # already routed
+            else
+              $scope.loadPreviousStep()
           else
             $scope.decideNextPage()
     add_defer.promise


make delete work

make delete work

--- lms/static/coffee/src/backbone_discussion/content.coffee
+++ lms/static/coffee/src/backbone_discussion/content.coffee
@@ -261,27 +261,18 @@
     @$(".discussion-content-edit").hide()
     @$(".discussion-content-wrapper").show()

-  delete: ->
-    if $content.hasClass("thread")
-      url = Discussion.urlFor('delete_thread', id)
-      c = confirm "Are you sure to delete thread \"" + $content.find("a.thread-title").text() + "\"?"
-    else
-      url = Discussion.urlFor('delete_comment', id)
+  delete: (event) ->
+    url = @model.urlFor('delete')
+    if @model.get('type') == 'thread'
+      c = confirm "Are you sure to delete thread \"#{@model.get('title')}\"?"
+    else
       c = confirm "Are you sure to delete this comment? "
-    if c != true
+    if not c
       return
-    Discussion.safeAjax
-      $elem: $(elem)
-      url: url
-      type: "POST"
-      dataType: "json"
-      data: {}
-      success: (response, textStatus) =>
-        if textStatus == "success"
-          $(content).remove()
-      error: (response, textStatus, e) ->
-        console.log e
-
+    $elem = $(event.target)
+    DiscussionUtil.post $elem, url, {}, (response, textStatus) => @$el.remove()
+    #TODO also do data-wise operation
+
   events:
     "click .thread-title": "toggleSingleThread"
     "click .discussion-show-comments": "toggleSingleThread"
@@ -336,6 +327,7 @@
     'downvote': -> DiscussionUtil.urlFor("downvote_#{@get('type')}", @id)
     'close': -> DiscussionUtil.urlFor('openclose_thread', @id)
     'update': -> DiscussionUtil.urlFor('update_thread', @id)
+    'delete': -> DiscussionUtil.urlFor('delete_thread', @id)

   initialize: ->
     @set('thread', @)
@@ -355,6 +347,7 @@
     'downvote': -> DiscussionUtil.urlFor("downvote_#{@get('type')}", @id)
     'endorse': -> DiscussionUtil.urlFor('endorse_comment', @id)
     'update': -> DiscussionUtil.urlFor('update_comment', @id)
+    'delete': -> DiscussionUtil.urlFor('delete_comment', @id)

   permalink: ->
     thread_id = @get('thread').id


Fix for undefined syncHandleDone

Fix for undefined syncHandleDone

--- client/components/ReviewResult.coffee
+++ client/components/ReviewResult.coffee
@@ -77,7 +77,7 @@
             result,
             comment: @state.commentText
         }
-        @props.syncHandleDone()
+        @props.syncHandleDone?()
         @props.handleReload()

     componentDidUpdate: (prevProps, prevState) ->


test fix

test fix


Updated cohtml-to-html5-converter (fixes)

--- src/cohtml-to-html5-converter.coffee
+++ src/cohtml-to-html5-converter.coffee
@@ -33,7 +33,7 @@
         currentHtml5Node.isSelfClosing = true

     else if node instanceof CohtmlTextNode
-      currentHtml5Node = new Html5Node parentHtml5Node, node.innerText
+      currentHtml5Node = new Html5TextNode parentHtml5Node, node.innerText

     else
       throw new Error 'Unknown type of node provided.'


Remove colon from users autocomplete

Remove colon from users autocomplete

--- packages/rocketchat-ui-message/message/popup/messagePopupConfig.coffee
+++ packages/rocketchat-ui-message/message/popup/messagePopupConfig.coffee
@@ -103,7 +103,7 @@
 					getUsersFromServerDelayed filter, items, cb

 				all =
-					_id: '@all'
+					_id: 'all'
 					username: 'all'
 					system: true
 					name: t 'Notify_all_in_this_room'
@@ -116,17 +116,8 @@

 				return items

-			getValue: (_id, collection, firstPartValue) ->
-				if _id is '@all'
-					if firstPartValue.indexOf(' ') > -1
-						return 'all'
-
-					return 'all:'
-
-				if firstPartValue.indexOf(' ') > -1
-					return _id
-
-				return _id + ':'
+			getValue: (_id) ->
+				return _id

 		return config


Fix add room route work

Fix add room route work

--- frontend/app/scripts/Router.coffee
+++ frontend/app/scripts/Router.coffee
@@ -42,9 +42,11 @@
       view.setRoom id if id?

     roomAdd: middleware.wrap (token)->
-      common.api.post_rooms_join(token).done (data)->
-        Backbone.trigger "rooms:needUpdate"
-        common.router "!/rooms/#{data.id}", {trigger:true}
+      common.api.post_rooms_join(token)
+        .done (data)->
+          Backbone.trigger "rooms:needUpdate"
+          common.router.navigate "!/rooms/#{data.id}", {trigger:true}
+        .fail -> common.router.navigate "#", {trigger: true}

     error404: middleware.wrap ->
       showPage Page.Error404Page


fix popover score status

fix popover score status

--- src/components/scores/late-work.cjsx
+++ src/components/scores/late-work.cjsx
@@ -16,7 +16,7 @@
       'pending'

   score: ->
-    if @state is 'accepted'
+    if @status is 'accepted'
       TH.getHumanUnacceptedScore(@task)
     else
       TH.getHumanScoreWithLateWork(@task)


Stop filtering out concept coach student courses

--- src/flux/course-listing.coffee
+++ src/flux/course-listing.coffee
@@ -67,9 +67,7 @@
         CourseListingActions.load() unless CourseListingStore.isLoading()
         true

-    allValidCourses: ->
-      _.reject( _.map( @_course_ids, CourseStore.get ), (course) ->
-        course.is_concept_coach and course.roles.length is 1 and course.roles[0].type is 'student'
-      )
+    allCourses: ->
+      return _.map @_course_ids, CourseStore.get

 module.exports = {CourseListingActions, CourseListingStore}


fix js for analytic

fix js for analytic

--- app/assets/javascripts/analytics.js.coffee
+++ app/assets/javascripts/analytics.js.coffee
@@ -47,7 +47,7 @@
           label.attr({text: "#{date.getFullYear()}/#{date.getMonth() + 1}"})

 $ ->
-  $('#analyticForm').on 'submit', (e) =>
+  $(document).on 'submit', '#analyticForm', (e) =>
     e.preventDefault()
     form = $(e.currentTarget)
     $.ajax


If corpus is empty, generate an empty string.

Fixes a bug where the word "Undefined" would be displayed if the corpus
were empty.

--- WordGenerator.coffee
+++ WordGenerator.coffee
@@ -76,7 +76,8 @@
 	# Generates a pseudorandom sequence (word) using the given model.
 generate = (maxLength, model, n=3) ->
 		# Pseudorandomly picks an element from containingObject with respect
-		# to each element's frequency property.
+		# to each element's frequency property.  If containingObject has no
+		# elements, returns null.
 	pickElement = (containingObject) ->
 		target = Math.random()
 		sum = 0.0
@@ -84,7 +85,7 @@
 			sum += element.frequency
 			if sum >= target then return elementName

-		# Returns the node of the probability tree (generate's "model" argument)
+		# Returns the node of the probability tree (generate()'s "model" argument)
 		# that represents the supplied sequence.  If no such node exists,
 		# returns null.
 	node = (sequence) ->
@@ -94,7 +95,12 @@
 			unless result? then return null
 		result

+	# Don't bother trying to generate a sequence if there's nothing to generate
+	# it from.
+	if model.count is 0 then return ""
+
 	result = ""
+
 	parent = model

 	until result.length >= maxLength or parent is null
@@ -122,7 +128,10 @@
 	maxLength = 8
 	currentModel = null

-	capitalize = (string) -> string[0].toUpperCase() + string.slice(1)
+	capitalize = (string) ->
+		if string.length > 0
+			string[0].toUpperCase() + string.slice(1)
+		else ""

 	generateAndShow = ->
 		$word.text capitalize generate maxLength, currentModel, n


Allow custom y axis tick format via options

--- app/assets/javascripts/datagraph.js.coffee
+++ app/assets/javascripts/datagraph.js.coffee
@@ -35,6 +35,7 @@
     }
     detailSmoothing: 10
     overviewSmoothing: 10
+    yAxisTickFormat: (y) -> y

   constructor: (element, @url, options) ->
     @element = $(element)
@@ -127,6 +128,7 @@

     yAxis = new Rickshaw.Graph.Axis.Y
       graph: @detailGraph
+      tickFormat: @options.yAxisTickFormat
     yAxis.render()

     detail = new Rickshaw.Graph.HoverDetail


fix: use <img> instead of backgroundImage (printing issue)

--- app/assets/javascripts/gmaps/extras.coffee
+++ app/assets/javascripts/gmaps/extras.coffee
@@ -38,19 +38,25 @@

       # cache drawn image
       @div ||= do =>
-        marker = $("
#{@number}
").css
+        marker = $("

#{@number}

").css
           position: "absolute"
           cursor: "pointer"
-          textAlign: 'center'
           height: image_size
           width: image_size
+          zIndex: 10000
+        .find('img').css
+          position: "absolute"
+          height: image_size
+          width: image_size
+        .parent().find('div').css
+          position: "absolute"
+          textAlign: 'center'
           lineHeight: "#{image_size}px"
+          width: "100%"
           fontWeight: "800"
           fontSize: font_size
-          color: "#507283"
-          backgroundImage: "url(#{image_url})"
-          zIndex: 10000
-
+          color: '#507283'
+        .parent()
         $(@getPanes().overlayImage).append(marker)

         google.maps.event.addDomListener marker[0], 'click', (e) =>
@@ -77,7 +83,7 @@
     @PREVENT_FIRST_IDLE = true

     directions: new google.maps.DirectionsService
-
+
     getLatLngBounds: ->
       if bounds = @getBounds()
         north_east = bounds.getNorthEast()


Fix flash message dismiss bug

Fix flash message dismiss bug

--- findaconf/blueprints/site/coffeescript/init.coffee
+++ findaconf/blueprints/site/coffeescript/init.coffee
@@ -31,7 +31,7 @@

 check_flash = ->
   flash_area = $('#flash')
-  flash_area.slideUp() if $('li', flash_area).length?
+  flash_area.slideUp() if not flash_area.find('li:visible').length

 fix_lang_menu = ->
   lang_menu = $('li.lang').first()


less chatty code

less chatty code

--- assets/js/services.coffee
+++ assets/js/services.coffee
@@ -1,38 +1,24 @@
-app.factory('clientSocket', ($rootScope) ->
-  socket = io.connect("/client")
+bindSocket = (scope, channelName) ->
+  socket = io.connect(channelName)
   {
     on: (eventName, callback) ->
       socket.on eventName,  () ->
         args = arguments
-        $rootScope.$apply( () ->
-          callback.apply(socket, args)
-        )
-    ,
-    emit: (eventName, data, callback) ->
-      socket.emit eventName, data, () ->
-        args = arguments;
-        $rootScope.$apply () ->
-          if (callback)
-            callback.apply(socket, args)
-  }
-)
-
-app.factory('adminSocket',  ($rootScope) ->
-  socket = io.connect("/admin")
-  {
-    on: (eventName, callback) ->
-      socket.on eventName,  () ->
-        args = arguments
-        $rootScope.$apply () ->
+        scope.$apply () ->
           callback.apply(socket, args)
     ,
     emit: (eventName, data, callback) ->
       socket.emit eventName, data, () ->
         args = arguments
-        $rootScope.$apply () ->
+        scope.$apply () ->
           if (callback)
             callback.apply(socket, args)
   }
-)
+
+app.factory 'clientSocket', ($rootScope) ->
+  bindSocket $rootScope, "/client"
+
+app.factory 'adminSocket',  ($rootScope) ->
+  bindSocket $rootScope, "/admin"

 angular.module("myApp.services", [])


remove coffeescript

remove coffeescript

--- app/assets/javascripts/transactions.coffee
+++ app/assets/javascripts/transactions.coffee
@@ -1,3 +0,0 @@
-# Place all the behaviors and hooks related to the matching controller here.
-# All this logic will automatically be available in application.js.
-# You can use CoffeeScript in this file: http://coffeescript.org/


Return false in click handlers to stop propagation

--- app/assets/rdb/PermissionComponents.coffee
+++ app/assets/rdb/PermissionComponents.coffee
@@ -31,15 +31,21 @@
       td className: 'rdb-roles', [
         Anchor
           className: if @props.model.isRead() then 'rdb-active'
-          onPrimary: => @refs['indicator'].track @props.model.setRead()
+          onPrimary: =>
+            @refs['indicator'].track @props.model.setRead()
+            false
           t 'rdb.permissions.read'
         Anchor
           className: if @props.model.isEdit() then 'rdb-active'
-          onPrimary: => @refs['indicator'].track @props.model.setEdit()
+          onPrimary: =>
+            @refs['indicator'].track @props.model.setEdit()
+            false
           t 'rdb.permissions.edit'
         Anchor
           className: if @props.model.isAdmin() then 'rdb-active'
-          onPrimary: => @refs['indicator'].track @props.model.setAdmin()
+          onPrimary: =>
+            @refs['indicator'].track @props.model.setAdmin()
+            false
           t 'rdb.permissions.admin'
       ]
       td className: 'rdb-actions', [


Fixing-custom-filters-with-epics

Fixing-custom-filters-with-epics

--- app/coffee/modules/controllerMixins.coffee
+++ app/coffee/modules/controllerMixins.coffee
@@ -193,6 +193,7 @@
         filters.status = urlfilters.status
         filters.assigned_to = urlfilters.assigned_to
         filters.owner = urlfilters.owner
+        filters.epic = urlfilters.epic

         @filterRemoteStorageService.getFilters(@scope.projectId, @.storeCustomFiltersName).then (userFilters) =>
             userFilters[name] = filters


check if stats are loaded before redraw chart

--- app/coffee/modules/taskboard/charts.coffee
+++ app/coffee/modules/taskboard/charts.coffee
@@ -89,13 +89,15 @@
         element = angular.element($el)

         $scope.$on "resize", ->
-            redrawChart(element, $scope.stats.days)
+            redrawChart(element, $scope.stats.days) if $scope.stats

         $scope.$on "taskboard:graph:toggle-visibility", ->
             $el.parent().toggleClass('open')

             # fix chart overflow
-            timeout(100, -> redrawChart(element, $scope.stats.days))
+            timeout(100, ->
+                redrawChart(element, $scope.stats.days) if $scope.stats
+            )

         $scope.$watch 'stats', (value) ->
             if not $scope.stats?


[Frontend validations] commented 'console.logs'

--- app/assets/javascripts/frontend/form-validation.js.coffee
+++ app/assets/javascripts/frontend/form-validation.js.coffee
@@ -234,47 +234,47 @@

     for _q in $(".question-block")
       question = $(_q)
-      console.log "----"
-      console.log question.find("h2").text()
+      # console.log "----"
+      # console.log question.find("h2").text()

       if question.hasClass("question-required") and not question.hasClass("question-date-by-years") and not question.hasClass("question-money-by-years")
-        console.log "validateRequiredQuestion"
+        # console.log "validateRequiredQuestion"
         @validateRequiredQuestion(question)

       if question.hasClass("question-number")
-        console.log "validateNumber"
+        # console.log "validateNumber"
         @validateNumber(question)

       if question.hasClass("question-money-by-years")
-        console.log "validateMoneyByYears"
+        # console.log "validateMoneyByYears"
         @validateMoneyByYears(question)

       if question.hasClass("question-date-by-years")
-        console.log "validateDateByYears"
+        # console.log "validateDateByYears"
         @validateDateByYears(question)

       if question.find(".match").length
-        console.log "validateMatchQuestion"
+        # console.log "validateMatchQuestion"
         @validateMatchQuestion(question)

       if question.hasClass("question-date-max")
-        console.log "validateMaxDate"
+        # console.log "validateMaxDate"
         @validateMaxDate(question)

       if question.hasClass("question-date-min")
-        console.log "validateMinDate"
+        # console.log "validateMinDate"
         @validateMinDate(question)

       if question.hasClass("question-date-between")
-        console.log "validateBetweenDate"
+        # console.log "validateBetweenDate"
         @validateBetweenDate(question)

       if $(".question-block[data-answer='overseas_sales-total-overseas-sales'] > .conditional-question").hasClass("show-question")
-        console.log "validateTotalOverseas"
+        # console.log "validateTotalOverseas"
         @validateTotalOverseas()

       if question.find(".validate-date-start-end").size() > 0
-        console.log "validateDateStartEnd"
+        # console.log "validateDateStartEnd"
         @validateDateStartEnd(question)

       #console.log @validates


Simplify centroid calculation methods

Simplify centroid calculation methods

--- app/assets/javascripts/leaflet/reactive_measure.js.coffee
+++ app/assets/javascripts/leaflet/reactive_measure.js.coffee
@@ -5,8 +5,6 @@
   # @return {number} polygon centroid
    ###
   __getCenter: ->
-
-    @projectLatlngs()
     @__project()
     points = @_rings[0]
     len = points.length
@@ -51,7 +49,6 @@
   # @return {number} polyline center
    ###
   __getCenter: ->
-    @projectLatlngs()
     @__project()
     i = undefined
     halfDist = undefined
@@ -93,12 +90,6 @@
     pxBounds = new (L.Bounds)
     @_rings = []
     @__projectLatlngs @_latlngs, @_rings, pxBounds
-    w = @__clickTolerance()
-    p = new (L.Point)(w, w)
-    if @getBounds().isValid() and pxBounds.isValid()
-      pxBounds.min._subtract p
-      pxBounds.max._add p
-      @_pxBounds = pxBounds
     return

   # recursively turns latlngs into a set of rings with projected coordinates
@@ -122,10 +113,6 @@
         i++
     return

-  __clickTolerance: ->
-    # used when doing hit detection for Canvas layers
-    (@options.stroke ? @options.weight / 2 : 0) + (L.Browser.touch ? 10 : 0)
-
 L.Draw.Polyline.include
   __addHooks: L.Draw.Polyline.prototype.addHooks
   __removeHooks: L.Draw.Polyline.prototype.removeHooks
@@ -209,9 +196,6 @@
       this._poly.on 'editdrag', @__onHandlerDrag, this

-L.Edit.Poly.mergeOptions
-  reactiveMeasure: true
-
 L.LatLng.prototype.toArray = ->
   [@lat, @lng]


Buttonbar

Buttonbar

- New parameter "size", when "big" Buttonbar should "maximize".

--- src/elements/Button/Buttonbar.coffee
+++ src/elements/Button/Buttonbar.coffee
@@ -27,11 +27,16 @@
 		for btn, idx in @_buttons
 			@addButton(btn, false)

+		if @_size
+			@addClass("cui-buttonbar--size-"+@_size)
+
 		@__checkVisibility()

 	initOpts: ->
 		super()
 		@addOpts
+			size:
+				check: ["big"]
 			buttons:
 				mandatory: true
 				default: []


Remove unnecessary model method

Remove unnecessary model method

--- app/assets/javascripts/rglossa/states/search_route.coffee
+++ app/assets/javascripts/rglossa/states/search_route.coffee
@@ -1,7 +1,4 @@
 App.SearchRoute = Em.Route.extend
-
-  model: (params) ->
-    corpus = @controllerFor('corpus').setCorpus(params['corpus_short_name'])

   renderTemplate: ->
     # Metadata selection is independent of the type of search interface, so


[Fixes #74409550] Close overlays on esc

[Fixes #74409550] Close overlays on esc

* Add app level handler for closeAction that closes the overlay

--- app/assets/javascripts/routes/application_route.js.coffee
+++ app/assets/javascripts/routes/application_route.js.coffee
@@ -55,3 +55,6 @@
         @disconnectOutlet
           outlet: 'overlay'
           parentView: 'application'
+
+    closeAction: ->
+      @send('closeOverlay')


separate pagination as react component

separate pagination as react component


fix console multiselect js

fix console multiselect js

--- app/assets/javascripts/folio/console/modules/_multiselect.coffee
+++ app/assets/javascripts/folio/console/modules/_multiselect.coffee
@@ -12,15 +12,22 @@
 else
   normalize = (str) -> str.toLowerCase()

+bindMultiSelects = ->
+  $('select[multiple]').multiSelect
+    selectableHeader: text(window.FolioConsole.translations.selectable)
+    selectionHeader: text(window.FolioConsole.translations.selected)
+
+if Turbolinks?
+  $(document)
+    .on 'turbolinks:load', bindMultiSelects
+
+    .on 'turbolinks:before-cache', ->
+      $('select[multiple]').multiSelect('destroy')
+
+else
+  $ bindMultiSelects
+
 $(document)
-  .on 'turbolinks:load', ->
-    $('select[multiple]').multiSelect
-      selectableHeader: text(window.FolioConsole.translations.selectable)
-      selectionHeader: text(window.FolioConsole.translations.selected)
-
-  .on 'turbolinks:before-cache', ->
-    $('select[multiple]').multiSelect('destroy')
-
   .on 'keyup', '.ms-filter', (e) ->
     $input = $(this)


Replace obj.unset('prop_name') with obj.prop_name = null (#5167)

--- bokehjs/src/coffee/models/tools/inspectors/crosshair_tool.coffee
+++ bokehjs/src/coffee/models/tools/inspectors/crosshair_tool.coffee
@@ -16,7 +16,7 @@
     for dim in @model.dimensions
       span = @model.spans[dim]
       if not frame.contains(vx, vy)
-        span.unset('computed_location')
+        span.computed_location = null
       else
         if dim == "width"
           span.computed_location = vy
@@ -26,7 +26,7 @@
   _move_exit: (e)->
     for dim in @model.dimensions
       span = @model.spans[dim]
-      span.unset('computed_location')
+      span.computed_location = null

 class CrosshairTool extends InspectTool.Model
   default_view: CrosshairToolView


fixes #267

fixes #267

--- chrome/content/zotero-better-bibtex/BetterBibTeXPatternFormatter.coffee
+++ chrome/content/zotero-better-bibtex/BetterBibTeXPatternFormatter.coffee
@@ -116,7 +116,7 @@
           creators.collaborators.push(name)

     return creators.editors || [] if onlyEditors
-    return creators.authors || creators.editors || creators.collaborators || creators.translators || []
+    return creators.authors || creators.editors || creators.translators || creators.collaborators || []

   methods:
     '0': (text) ->