Fix BackgroundLayer when no Framer.Device is present

--- framer/BackgroundLayer.coffee
+++ framer/BackgroundLayer.coffee
@@ -15,7 +15,7 @@
 		@sendToBack()
 		@layout()
 		@_context.domEventManager.wrap(window).addEventListener("resize", @layout)
-		Framer.Device.on("change:orientation", @layout)
+		Framer.Device?.on("change:orientation", @layout)

 	layout: =>
 		if @parent


Fix linter errors

Fix linter errors

--- lib/autocomplete-manager.coffee
+++ lib/autocomplete-manager.coffee
@@ -35,7 +35,7 @@
     @ready = true

   updateCurrentEditor: (currentPaneItem) =>
-    return if !currentPaneItem? or currentPaneItem is @editor
+    return if not currentPaneItem? or currentPaneItem is @editor

     @editorSubscriptions?.dispose()
     @editorSubscriptions = null
@@ -113,7 +113,7 @@

   getSuggestionsFromProviders: (options) =>
     providers = @providerManager.providersForScopeChain(options.scopeChain)
-    providerPromises = providers?.map (provider) -> provider?.requestHandler(options)
+    providerPromises = providers?.map((provider) -> provider?.requestHandler(options))
     return unless providerPromises?.length
     @currentSuggestionsPromise = suggestionsPromise = Promise.all(providerPromises)
       .then(@mergeSuggestionsFromProviders)


file selection

file selection

--- lib/build/ios-build-view.coffee
+++ lib/build/ios-build-view.coffee
@@ -41,21 +41,18 @@
     ]
     .forEach (each) ->
       #disable input
-      # each.view.setInputEnabled false
+      each.view.setInputEnabled false
       #select file
       each.view.on 'click', ->
-        openFile({
+        openFile
           title: "Select .#{each.suffix} File"
           filters: [{name: ".#{each.suffix} file", extensions: [each.suffix]}]
-        })
         .then (destPath) ->
-          console.log "!!! #{each.view.setText}"
-          each.view.setText(destPath)
+          each.view.setText destPath[0]

   onClickIcon: ->
-    openFile({
+    openFile
       title: 'Select Icon Image'
       filters: [{name: "png image", extensions: ['png']}]
-    })
     .then (destPath) =>
-      @icon.attr('src', destPath) if destPath
+      @icon.attr('src', destPath[0]) if destPath.length > 0


LEV-88 isEndSegment in segment

LEV-88 isEndSegment in segment

--- modules/levelcreator/app/assets/javascripts/level_creator/plugins/segment_importer.coffee
+++ modules/levelcreator/app/assets/javascripts/level_creator/plugins/segment_importer.coffee
@@ -86,7 +86,8 @@
     @setRandomColor(segments)
     @setRandomColor2(segments)
     @setRandomColor3(segments)
-    @setProbability(segments, input.mission)
+    @setMissionDataToSegments(segments, input.mission)
+

     #for segment in segments
     #  @setArtPath(segment, width, height)
@@ -490,9 +491,15 @@

-  setProbability: (segments, mission) ->
+  setMissionDataToSegments: (segments, mission) ->

     for segment in segments
       es = _.find(mission.possibleEnds, (m) => m.id is segment.value)
       if es?
         segment.probability = es.probability
+        segment.isEndSegment = true
+      else
+        segment.isEndSegment = false
+
+
+      segment.isStartSegment = segment.value is mission.start.id


Search for similar issues before reporting

--- lib/deprecation-cop-view.coffee
+++ lib/deprecation-cop-view.coffee
@@ -59,6 +59,8 @@
     # afterAttach is called 2x when dep cop is the active pane item on reload.
     return if @subscribedToEvents

+    self = this
+
     @openBlogPost.on 'click', =>
       require('shell').openExternal('http://blog.atom.io/2015/05/01/removing-deprecated-apis.html')
       false
@@ -81,23 +83,47 @@
       atom.open(pathsToOpen: [pathToOpen])

     @on 'click', '.issue-url', ->
-      openExternally = (urlToOpen=@dataset.issueUrl) =>
-        require('shell').openExternal(urlToOpen)
-
-      if process.platform is 'win32'
+      self.openIssueUrl(@dataset.repoUrl, @dataset.issueUrl, @dataset.issueTitle)
+      false
+
+    @subscribedToEvents = true
+
+  findSimilarIssues: (repoUrl, issueTitle) ->
+    url = "https://api.github.com/search/issues"
+    repo = repoUrl.replace /http(s)?:\/\/(\d+\.)?github.com\//gi, ''
+    query = "#{issueTitle} repo:#{repo}"
+
+    new Promise (resolve, reject) =>
+      $.ajax "#{url}?q=#{encodeURI(query)}&sort=created",
+        accept: 'application/vnd.github.v3+json'
+        contentType: 'application/json'
+        success: (data) =>
+          if data.items?
+            issues = {}
+            for issue in data.items
+              issues[issue.state] = issue if issue.title.indexOf(issueTitle) > -1 and not issues[issue.state]?
+            return resolve(issues) if issues.open? or issues.closed?
+          resolve(null)
+        error: -> resolve(null)
+
+  openIssueUrl: (repoUrl, issueUrl, issueTitle) ->
+    openExternally = (urlToOpen) =>
+      require('shell').openExternal(urlToOpen)
+
+    @findSimilarIssues(repoUrl, issueTitle).then (issues) ->
+      if issues?.open or issues?.closed
+        issue = issues.open or issues.closed
+        openExternally(issue.html_url)
+      else if process.platform is 'win32'
         $.ajax 'http://git.io',
           type: 'POST'
-          data: url: @dataset.issueUrl
+          data: url: issueUrl
           success: (data, status, xhr) ->
             openExternally(xhr.getResponseHeader('Location'))
           error: ->
-            openExternally()
+            openExternally(issueUrl)
       else
-        openExternally()
-
-      false
-
-    @subscribedToEvents = true
+        openExternally(issueUrl)

   destroy: ->
     @subscriptions.dispose()
@@ -158,10 +184,14 @@

     return

-  createIssueUrl: (packageName, deprecation, stack) ->
+  getRepoUrl: (packageName) ->
     return unless repo = atom.packages.getLoadedPackage(packageName)?.metadata?.repository
     repoUrl = repo.url ? repo
-    repoUrl = repoUrl.replace(/\.git$/, '')
+    repoUrl.replace(/\.git$/, '')
+
+  createIssueUrl: (packageName, deprecation, stack) ->
+    repoUrl = @getRepoUrl(packageName)
+    return unless repoUrl

     title = "#{deprecation.getOriginName()} is deprecated."
     stacktrace = stack.map(({functionName, location}) -> "#{functionName} (#{location})").join("\n")
@@ -169,9 +199,8 @@
     "#{repoUrl}/issues/new?title=#{encodeURI(title)}&body=#{encodeURI(body)}"

   createSelectorIssueUrl: (packageName, deprecation, sourcePath) ->
-    return unless repo = atom.packages.getLoadedPackage(packageName)?.metadata?.repository
-    repoUrl = repo.url ? repo
-    repoUrl = repoUrl.replace(/\.git$/, '')
+    repoUrl = @getRepoUrl(packageName)
+    return unless repoUrl

     title = deprecation.message
     body = "In #{sourcePath}: #{deprecation.message}"
@@ -220,9 +249,11 @@
                   @div class: 'list-item deprecation-message', =>
                     @raw marked(deprecation.getMessage())

-                  if packageName and url = self.createIssueUrl(packageName, deprecation, stack)
+                  if packageName and issueUrl = self.createIssueUrl(packageName, deprecation, stack)
+                    repoUrl = self.getRepoUrl(packageName)
+                    issueTitle = "#{deprecation.getOriginName()} is deprecated."
                     @div class: 'btn-toolbar', =>
-                      @button class: 'btn issue-url', 'data-issue-url': url, 'Report Issue'
+                      @button class: 'btn issue-url', 'data-issue-title': issueTitle, 'data-repo-url': repoUrl, 'data-issue-url': issueUrl, 'Report Issue'

                   @div class: 'stack-trace', =>
                     for {functionName, location, fileName} in stack
@@ -265,6 +296,9 @@
                       @div class: 'list-item deprecation-message', =>
                         @raw marked(deprecation.message)

-                      if url = self.createSelectorIssueUrl(packageName, deprecation, sourcePath)
+                      if issueUrl = self.createSelectorIssueUrl(packageName, deprecation, sourcePath)
+                        repoUrl = self.getRepoUrl(packageName)
+                        issueTitle = deprecation.message
+
                         @div class: 'btn-toolbar', =>
-                          @button class: 'btn issue-url', 'data-issue-url': url, "Report Issue"
+                          @button class: 'btn issue-url', 'data-issue-title': issueTitle, 'data-repo-url': repoUrl, 'data-issue-url': issueUrl, 'Report Issue'


Add refresh button

Add refresh button

--- lib/deprecation-cop-view.coffee
+++ lib/deprecation-cop-view.coffee
@@ -8,13 +8,18 @@
   @content: ->
     @div class: 'deprecation-cop pane-item', tabindex: -1, =>
       @div class: 'panel', =>
-        @div class: 'panel-heading', "Deprecated calls"
+        @div class: 'panel-heading', =>
+          @div class: 'btn-toolbar pull-right', =>
+            @div class: 'btn-group', =>
+              @button outlet: 'refreshButton', class: 'btn refresh', 'Refresh'
+          @span "Deprecated calls"
         @ul outlet: 'list', class: 'list-tree has-collapsable-children padded'

   initialize: ({@uri}) ->
     @update()
     @subscribe this, 'click', '.list-nested-item', -> $(this).toggleClass('collapsed')
-    @subscribe Grim, 'updated', => # @update()
+    @subscribe Grim, 'updated', => @refreshButton.show()
+    @refreshButton.click => @update()

   destroy: ->
     @detach()
@@ -51,6 +56,7 @@
     Error.prepareStackTrace(@defaultError, stack)

   update: ->
+    @refreshButton.hide()
     methodList = []
     methodList.push [method, metadata] for method, metadata of Grim.getLog()
     methodList.sort (a, b) -> b[1].count - a[1].count


Allow native key bindings

Allow native key bindings

--- lib/deprecation-cop-view.coffee
+++ lib/deprecation-cop-view.coffee
@@ -7,7 +7,7 @@
 module.exports =
 class DeprecationCopView extends ScrollView
   @content: ->
-    @div class: 'deprecation-cop pane-item', tabindex: -1, =>
+    @div class: 'deprecation-cop pane-item native-key-bindings', tabindex: -1, =>
       @div class: 'panel', =>
         @div class: 'panel-heading', =>
           @div class: 'btn-toolbar pull-right', =>


allow password resets to be performed when site is not public by adding routes into white list

--- services/web/app/coffee/Features/PasswordReset/PasswordResetRouter.coffee
+++ services/web/app/coffee/Features/PasswordReset/PasswordResetRouter.coffee
@@ -1,11 +1,14 @@
 PasswordResetController = require("./PasswordResetController")
+AuthenticationController = require('../Authentication/AuthenticationController')

 module.exports =
 	apply: (app) ->

 		app.get  '/user/password/reset', PasswordResetController.renderRequestResetForm
 		app.post  '/user/password/reset', PasswordResetController.requestReset
+		AuthenticationController.addEndpointToLoginWhitelist '/user/password/reset'

 		app.get '/user/password/set', PasswordResetController.renderSetPasswordForm
 		app.post '/user/password/set', PasswordResetController.setNewUserPassword
+		AuthenticationController.addEndpointToLoginWhitelist '/user/password/set'


Fixed name collision in ion_range_slider example (#7850)

The local variable 'input' overwrites the 'input' from
core/dom if more than one IonRangeSlider is added.

--- sphinx/source/docs/user_guide/examples/extensions_ion_range_slider.coffee
+++ sphinx/source/docs/user_guide/examples/extensions_ion_range_slider.coffee
@@ -76,8 +76,8 @@
       onFinish: (data) => @slidestop(data),
     }

-    input = @$el.find('.slider')[0]
-    slider = jQuery(input).ionRangeSlider(opts)
+    inp = @$el.find('.slider')[0]
+    slider = jQuery(inp).ionRangeSlider(opts)
     range = [from, to]
     @$el.find( "##{ @model.id }" ).val( range.join(' - '))
     @$el.find('.bk-slider-parent').height(@model.height)


Add more list unit tests

Add more list unit tests

--- test/value.coffee
+++ test/value.coffee
@@ -153,7 +153,7 @@
 		}
 	'''

-test "list", ->
+test "space-separated list", ->
 	assert.compileTo '''
 		body {
 			font-family: foo bar baz;
@@ -164,7 +164,7 @@
 		}
 	'''

-test "list seperated by commas", ->
+test "comma-separated list", ->
 	assert.compileTo '''
 		body {
 			font-family: foo,bar,baz;
@@ -175,6 +175,28 @@
 		}
 	'''

+test "slash-separated list", ->
+	assert.compileTo '''
+		body {
+			font: 14px/1.2;
+		}
+	''', '''
+		body {
+			font: 14px/1.2;
+		}
+	'''
+
+test "mix-separated list", ->
+	assert.compileTo '''
+		body {
+			font: normal 12px/1.25 font1, font2;
+		}
+	''', '''
+		body {
+			font: normal 12px/1.25 font1, font2;
+		}
+	'''
+
 test "list separated by slashes", ->
 	assert.compileTo '''
 		body {


bugfix in lookup: find id prefix by searching for the first dot

--- lib/Context.coffee
+++ lib/Context.coffee
@@ -1,7 +1,7 @@

 events = require 'events'

-ACTIONS = ['configured', 'booted', 'started', 'running', 'shutdown', 'stopped', 'message']
+ACTIONS = ['configured', 'booted', 'started', 'running', 'shutdown', 'stopped']

 USELOOKUPSCACHE = false
 LOOKUPSCACHE = {}
@@ -550,7 +550,7 @@
                                 child.forIdentity identity, _try

                             # 2. the prefix of name matches child.id
-                            else if name.substr(0, id.length) is id
+                            else if name.substr(0, name.indexOf '.') is id

                                 @logger.debug 'searching for %s in %s', name.substr(id.length+1), child.ID

@@ -575,7 +575,7 @@
                     ##
                     ##
                     ##
-                    else if name.substr(0, @id.length) is @id
+                    else if name.substr(0, name.indexOf '.') is @id

                         @lookup name.substr(@id.length + 1), identity, _try

@@ -793,13 +793,4 @@

             return @

-
-        ##
-        ##
-        ##
-        _message: (msg)->
-
-            @logger.info 'message recived:', msg
-
-            @_emit 'message:'+msg.topic
-
+


context: fix arguments

context: fix arguments

--- lib/context.coffee
+++ lib/context.coffee
@@ -4,7 +4,7 @@
 {flatten, merge} = require './misc'

 class Context extends EventEmitter
-  constructor: (contexts, @config, @command)->
+  constructor: (contexts, @config)->
     @_contexts = contexts
     options = {}
     options.cache = true
@@ -74,6 +74,6 @@
     return if has_module.length then has_module else false

-module.exports = (config, command) ->
-  return new Context config, command
+module.exports = (contexts, config) ->
+  return new Context contexts, config
 module.exports.Context = Context


virtualization controller: WIP vm purchases

--- client/app/MainApp/VirtualizationController.coffee
+++ client/app/MainApp/VirtualizationController.coffee
@@ -273,7 +273,6 @@
     KD.remote.api.JVM.fetchDefaultVm callback

   createDefaultVM: (callback)->
-
     @hasDefaultVM (err, state)->
       return warn 'Default VM already exists.'  if state

@@ -342,18 +341,18 @@

     productForm = new VmProductForm

-    paymentController = KD.getSingleton 'paymentController'
-
-    KD.whoami().fetchPlansAndSubscriptions ['vm'], (err, plansAndSubscriptions) =>
+    pay = KD.getSingleton 'paymentController'
+
+    KD.whoami().fetchPlansAndSubscriptions ['vm'], (err, plansAndSubs) =>
       return  if KD.showError err

-      { subscriptions } = paymentController
-                            .groupPlansBySubscription plansAndSubscriptions
+      { subscriptions } = pay.groupPlansBySubscription plansAndSubs

       productForm.setCurrentSubscriptions subscriptions

     productForm.on 'PackOfferingRequested', (subscription) ->
       options = targetOptions: selector: tags: 'vm'
+
       KD.getGroup().fetchProducts 'pack', options, (err, packs) ->
         return  if KD.showError err

@@ -370,28 +369,31 @@
       width   : 500
       overlay : yes

-    workflow.on 'DataCollected', @bound 'provisionVm'
-
-    workflow.on 'Cancel', -> modal.destroy()
-
-    workflow.enter()
+    workflow
+      .on('DataCollected', @bound 'provisionVm')
+      .on('Cancel', modal.bound 'destroy')
+      .enter()

   provisionVm: ({ subscription, paymentMethod, productData })->
+
+    { JVM } = KD.remote.api
+
     { plan, pack } = productData

     if paymentMethod and not subscription

-      plan.subscribe paymentMethod.paymentMethodId, (err, subscription) =>
+      return plan.subscribe paymentMethod.paymentMethodId, (err, subscription) =>
         return  if KD.showError err

         @provisionVm { subscription, productData }

-    subscription.debit pack, (err, blah) ->
-      debugger
-
+    subscription.debit pack, (err, nonce) ->
       return  if KD.showError err

-      debugger
+      JVM.createVmByNonce nonce, (err, vm) ->
+        return  if KD.showError err
+
+        debugger

   askForApprove:(command, callback)->


Adds comment

Adds comment

--- client/components/autocomplete_select/index.coffee
+++ client/components/autocomplete_select/index.coffee
@@ -25,6 +25,7 @@
     @autocomplete = new Autocomplete _.extend _.pick(@props, 'url', 'filter'),
       el: $(@refs.input?.getDOMNode())
       selected: (e, item) =>
+        # Deferring because of click race condition
         _.defer => @setState value: item.value, id: item.id
         @props.selected? e, item


bin: Adding a few CLI options

bin: Adding a few CLI options

--- src/bin/gitwalk.coffee
+++ src/bin/gitwalk.coffee
@@ -10,15 +10,15 @@
 gitwalk = require '../lib/gitwalk'
 processors = require '../lib/processors'
 logger = require '../lib/logger'
+cache = require '../lib/cache'

 program
   .version pkginfo.version
   .usage '[options] <expr...> <proc> <cmd...>'
-  #.option '-a, --async', 'Process the repositories asynchronously in parallel'
-  #.option '-r, --regex', 'Use regular expressions instead of minimax matching'
-  #.option '-c, --clear-cache', 'Clear the cache and exit'
-  #.option '-l, --logging-level', 'Force logging level'
-  #.option '-m, --match-only', 'Only print the list of matching repos'
+  .option '-w, --wipe-cache', 'Clear the cache and exit'
+  .option '-c, --colours <setting>', 'Either \'always\', \'off or \'auto\' (default)'
+  .option '-v, --verbose', 'Show debugging prints'
+  .option '-d, --dry-run', 'Only print the list of matching repos'
   .parse process.argv

 expressions = []
@@ -26,28 +26,53 @@
 procName = null
 procArgs = []

-if program.args.length == 0
-  program.outputHelp()
-  process.exit 1
+logger.set
+  colours: program.colours
+  level: if program.verbose then 'debug' else null

-while program.args.length > 0
-  arg = program.args.shift()
-  if arg of processors
-    proc = processors[arg]
-    procName = arg
-    procArgs = program.args
-    break
-  else
-    expressions.push arg
+switch
+  when program.wipeCache
+    cache.clearCache (err) ->
+      rv = 0
+      if err?
+        logger.error err
+        rv = 1

-if !('shell' of proc)
-  logger.error "#{procName} isn't supported on the command-line yet"
-  process.exit 1
-
-gitwalk expressions, proc.shell(procArgs), (err) ->
-  if err?
-    #console.log err.stack
-    logger.error err
+      process.exit rv
+  when program.args.length is 0
+    program.outputHelp()
     process.exit 1
   else
-    process.exit()
+    while program.args.length > 0
+      arg = program.args.shift()
+      if arg of processors
+        proc = processors[arg]
+        procName = arg
+        procArgs = program.args
+        break
+      else
+        expressions.push arg
+
+    if program.dryRun
+      gitwalk expressions, null, (err) ->
+        if err?
+          logger.error err
+          process.exit 1
+        else
+          process.exit()
+    else
+      unless proc?
+        logger.error 'Missing processor'
+        program.outputHelp()
+        process.exit 1
+
+      if !('shell' of proc)
+        logger.error "#{procName} isn't supported on the command-line yet"
+        process.exit 1
+
+      gitwalk expressions, proc.shell(procArgs), (err) ->
+        if err?
+          logger.error err
+          process.exit 1
+        else
+          process.exit()


Fix a save bug introduced in last patch.

--- salvus/page/top_navbar.coffee
+++ salvus/page/top_navbar.coffee
@@ -113,13 +113,14 @@
     remove_page: (id) ->
         p = @pages[id]
         if p?
+            if p.onclose?
+                # save unsaved work, etc.
+                p.onclose()
             if p.button.hasClass("active")
                 @switch_to_next_available_page(id)
             # Now actually the page
             p.page.remove()
             p.button.remove()
-            if p.onclose?
-                p.onclose()
             delete @pages[id]

             # Now switch to the next page


Critical bug fix

Critical bug fix

--- lib/quick-highlight-view.coffee
+++ lib/quick-highlight-view.coffee
@@ -39,6 +39,7 @@
           if selection.isEmpty()
             @clearSelectionHighlight()
           else
+            @clearSelectionHighlight()
             highlightSelection(selection)
          )


disabled tooltip

disabled tooltip

--- coffee/vis.coffee
+++ coffee/vis.coffee
@@ -4,7 +4,7 @@
     @width = 940
     @height = 600

-    @tooltip = CustomTooltip("gates_tooltip", 240)
+    # @tooltip = CustomTooltip("gates_tooltip", 240)

     # locations the nodes will move towards
     # depending on which view is currently being
@@ -289,12 +289,12 @@
     content +="Unit of Study: #{data.org}
"
     content +="Discipline: #{data.uos_id}
"
     content +="My class size is: #{data.class}"
-    @tooltip.showTooltip(content,d3.event)
+    # @tooltip.showTooltip(content,d3.event)

   hide_details: (data, i, element) =>
     d3.select(element).attr("stroke", (d) => d3.rgb(@fill_color(d.group)).darker())
-    @tooltip.hideTooltip()
+    # @tooltip.hideTooltip()

 root = exports ? this


remove unnecessary blank lines

remove unnecessary blank lines

--- workers/social/lib/social/models/computeproviders/provisioner.test.coffee
+++ workers/social/lib/social/models/computeproviders/provisioner.test.coffee
@@ -116,7 +116,6 @@
   it 'should be able to fetch provisioner data', (done) ->

     withConvertedUserAndProvisioner ({ client, provisioner }) ->
-
       selector = { slug : provisioner.slug }
       JProvisioner.some$ client, selector, (err, provisioners) ->
         expect(err).to.not.exist
@@ -135,7 +134,6 @@
   it 'should be able to fetch provisioner data', (done) ->

     withConvertedUserAndProvisioner ({ client, provisioner }) ->
-
       selector = { slug : provisioner.slug }
       JProvisioner.one$ client, selector, (err, provisioner_) ->
         expect(err).to.not.exist
@@ -156,7 +154,6 @@

     withConvertedUserAndProvisioner ({ client, provisioner }) ->

-
       queue = [

         ->


Switch to the status field we actually use

--- scripts/jira-linkifier.coffee
+++ scripts/jira-linkifier.coffee
@@ -68,4 +68,4 @@
       .get() (err, res, body) ->
         issue = JSON.parse(body)
         console.log("Got back issue: " + body)
-        mention.send(issue.key + ": " + issue.fields.summary + " (status: " + issue.fields.customfield_10300 + ")")
+        mention.send(issue.key + ": " + issue.fields.summary + " (status: " + issue.fields.status.name + ")")


Another attempt at link formatting

Another attempt at link formatting

--- scripts/jira-linkifier.coffee
+++ scripts/jira-linkifier.coffee
@@ -86,6 +86,6 @@

 issue_summary = (issue) ->
   if issue.fields
-    "^lt;" + process.env.HUBOT_JIRA_INSTANCE_URL + "/browse/" + issue.key + "|" + issue.key + ">" + ": " + issue.fields.summary + " (status: " + issue.fields.status.name + ")"
+    process.env.HUBOT_JIRA_INSTANCE_URL + "/browse/" + issue.key + "|" + issue.key + ": " + issue.fields.summary + " (status: " + issue.fields.status.name + ")"
   else
     null


Adding a manual watch for MOBILE- issues

--- scripts/jira-linkifier.coffee
+++ scripts/jira-linkifier.coffee
@@ -27,10 +27,12 @@
     projects.push shortcode
     robot.brain.set 'jira-projects', projects

-    robot.hear (new RegExp shortcode + "-([0-9]*)\s", "i"), (mention) ->
-      msg.send("Issue at: https://jira.brandnetworksinc.com/browse/" + shortcode + "-" + mention.match[1])
+

     msg.send "Watching that project for you"
+
+  robot.hear ("MOBILE-([0-9]*)", "i"), (mention) ->
+    msg.send("Issue at: https://jira.brandnetworksinc.com/browse/" + "MOBILE" + "-" + mention.match[1])

   robot.respond /stop watching ?(.+)?/i, (msg) ->
     projects = robot.brain.get('jira-projects') or []


Debug the whitelist.

Debug the whitelist.

--- scripts/whitelist_room.coffee
+++ scripts/whitelist_room.coffee
@@ -25,5 +25,6 @@
       # We're done
       robot.logger.debug 'Received message from non-whitelisted room: ' + room
       robot.logger.debug 'Whitelist: ' + whitelist
+      robot.logger.debug room == process.env.HUBOT_ROOM_WHITELIST
       context.response.message.finish()
       done()


fix search datatable (#1896)

fix search datatable (#1896)

--- BackofficeBundle/Resources/public/coffee/dataTable/header/DataTableViewSearchHeader.coffee
+++ BackofficeBundle/Resources/public/coffee/dataTable/header/DataTableViewSearchHeader.coffee
@@ -20,7 +20,7 @@
       'api'
       'domContainer'
     ])
-    @options.api.on 'column-visibility.dt', @toggleColumn*
+    @options.api.on 'column-visibility.dt', @toggleColumn

     # This view not needed these templates, there are loaded here to optimize number of request
     @loadTemplates [


Fixed help showing on update cli

Fixed help showing on update cli

--- src/cli/plugins.coffee
+++ src/cli/plugins.coffee
@@ -238,6 +238,7 @@
 					scaffolding.plugins.info.getPluginsJson()
 						.then (plugins) ->
 							chainPluginsUpdate plugins
+			return main_defer.promise

 		doGetInfo = (name, done, fetch) ->
 			text = ''
@@ -318,7 +319,8 @@
 								main_defer.resolve()
 			return main_defer.promise

-		console.log 'Unknown command: ' + args[0].yellow
+		if args[0]?
+			console.log 'Unknown command: ' + args[0].yellow
 		@help()
 		return main_defer.promise


refs #31 Removes user rankings details view.

--- app/assets/javascripts/voluntary_ranking/views/user/rankings/details_view.js.coffee
+++ app/assets/javascripts/voluntary_ranking/views/user/rankings/details_view.js.coffee
@@ -1,8 +0,0 @@
-Volontariat.UserRankingsDetailsView = Ember.View.extend
-  didInsertElement: ->
-    $('input[data-autocomplete]').each (k, v) ->
-      $(v).autocomplete
-        source: $(this).attr('data-autocomplete'),
-        select: (event, ui) ->
-          $(this).val(ui.item.value)
-          false


Add new atom config

Add new atom config

--- .atom/config.cson
+++ .atom/config.cson
@@ -13,6 +13,8 @@
   core:
     disabledPackages: [
       "atom-jshint"
+      "linter-htmlhint"
+      "linter-bootlint"
     ]
   "atom-beautify":
     _analyticsUserId: "23d4c686-6cc4-47c2-80ee-a596dbed4987"
@@ -42,3 +44,9 @@
   "linter-jsxhint":
     use_6to5_transform: true
   "autocomplete-plus": {}
+".coffee.jsx.source":
+  editor:
+    preferredLineLength: 120
+".js.jsx.source":
+  editor:
+    preferredLineLength: 120


cleancss 2 api

cleancss 2 api

--- monocat.coffee
+++ monocat.coffee
@@ -50,8 +50,7 @@
             logErr "cannot read `#{ path }`"
             process.exit 1

-          $el.after("<style>#{ cleanCss.process data.toString() }</style>").remove()
-          deliver ++completed
+          min   = new CleanCss().minify data.toString()

           deliver() if ++completed is total


Maintenance: Make ticket number options translatable.

--- app/assets/javascripts/app/controllers/_settings/area_ticket_number.coffee
+++ app/assets/javascripts/app/controllers/_settings/area_ticket_number.coffee
@@ -79,6 +79,11 @@
       el = $(App.view("settings/#{preferences_setting}")(
         setting: setting
       ))
+
+      for form_entry in setting.options['form']
+        if form_entry['tag'] is 'boolean'
+          form_entry['translate'] = true
+
       new App.ControllerForm(
         el: el.find('.js-formItem'),
         model: { configure_attributes: setting.options['form'], className: '' }


Yandex share localization

Yandex share localization

--- app/assets/javascripts/langtrainer_frontend_backbone/application.js.coffee
+++ app/assets/javascripts/langtrainer_frontend_backbone/application.js.coffee
@@ -95,6 +95,9 @@
     _.each $.cookie(), (value, key) ->
       $.removeCookie(key)

+  locale: ->
+    @currentUser.get('native_language_slug')
+
   t: (token) ->
     chain = token.split('.')
     result = @locales[@currentUser.get('native_language_slug')]


mini command line was temporarily broken

--- salvus/page/project.coffee
+++ salvus/page/project.coffee
@@ -139,12 +139,12 @@
         cmdline.keydown (evt) =>
             if evt.which == 13 # enter
                 try
-                    that.command_line_exec()
+                    @command_line_exec()
                 catch e
                     console.log(e)
                 return false
             if evt.which == 27 # escape
-                @container?.find(".project-command-line-output").hide()
+                @container.find(".project-command-line-output").hide()
                 return false
         # TODO: this will be for command line tab completion
         #cmdline.keydown (evt) =>


forget images

forget images

--- scripts/favorite-images.coffee
+++ scripts/favorite-images.coffee
@@ -2,6 +2,7 @@
 #
 # save image URL as SOME NAME FOR THE IMAGE -> save an image
 # show me SOME NAME FOR THE IMAGE -> show an image
+# forget image SOME NAME FOR THE IMAGE -> forget it
 # favorite images -> see a list
 #

@@ -13,6 +14,13 @@
     robot.brain.data.favorite_images or= {}
     robot.brain.data.favorite_images[makeImageKey(msg.match[2])] = msg.match[1]
     msg.send "OK"
+
+  robot.respond /forget image (.*)/i, (msg) ->
+    if robot.brain.data.favorite_images[makeImageKey(msg.match[1])]?
+      delete robot.brain.data.favorite_images[makeImageKey(msg.match[1])]
+      msg.send "OK forgot it."
+    else
+      msg.send "Not found. Use 'save image [URL] as [NAME]' to save one."

   robot.respond /show me (.*)/i, (msg) ->
     robot.brain.data.favorite_images or= {}


Hide DOM element directly instead of calling hide on view

--- lib/bracket-matcher-view.coffee
+++ lib/bracket-matcher-view.coffee
@@ -87,8 +87,8 @@

   updateMatch: ->
     if @pairHighlighted
-      @startView.hide()
-      @endView.hide()
+      @startView.element.style.display = 'none'
+      @endView.element.style.display = 'none'
     @pairHighlighted = false
     @tagHighlighted = false

@@ -202,12 +202,11 @@
     startPixelPosition = @editor.pixelPositionForBufferPosition(bufferRange.start)
     endPixelPosition = @editor.pixelPositionForBufferPosition(bufferRange.end)

-    [element] = view
-    element.style.display = 'block'
-    element.style.top = "#{startPixelPosition.top}px"
-    element.style.left = "#{startPixelPosition.left}px"
-    element.style.width = "#{endPixelPosition.left - startPixelPosition.left}px"
-    element.style.height = "#{@editorView.lineHeight}px"
+    view.element.style.display = ''
+    view.element.style.top = "#{startPixelPosition.top}px"
+    view.element.style.left = "#{startPixelPosition.left}px"
+    view.element.style.width = "#{endPixelPosition.left - startPixelPosition.left}px"
+    view.element.style.height = "#{@editorView.lineHeight}px"

   moveStartView: (bufferRange) ->
     @moveHighlightView(@startView, bufferRange)


fix bad parentData in afFileUpload helper

--- lib/client/autoform-file.coffee
+++ lib/client/autoform-file.coffee
@@ -101,12 +101,13 @@
 		if af &&  af.submitType == 'insert'
 			doc = af.doc

+		parentData = Template.parentData(0).value or Template.parentData(4).value
 		if Session.equals('fileUpload['+name+']', 'delete-file')
 			return null
 		else if Session.get('fileUpload['+name+']')
 			file = Session.get('fileUpload['+name+']')
-		else if Template.parentData(4).value
-			file = Template.parentData(4).value
+		else if parentData
+			file = parentData
 		else
 			return null

@@ -128,7 +129,7 @@
 				filename = file
 				src = filename
 		if filename
-			obj =
+			obj =
 				template: getTemplate(filename)
 				data:
 					src: src
@@ -153,4 +154,4 @@
 			console.log doc
 			doc
 		else
-			null+			null


Bug fix.

Bug fix.

--- lib/collections/projects.coffee
+++ lib/collections/projects.coffee
@@ -26,6 +26,4 @@
       submitted: new Date()
       kind: 'project'
     projectId = Projects.insert project
-    text = user.username + ' added you as project member to ' + project.title
-    createNotification(member, user._id, projectId, text) for member in project.members
     return {_id: projectId}


fix compound reference in db_feed_helper

--- helpers/db_feed_helper.coffee
+++ helpers/db_feed_helper.coffee
@@ -7,10 +7,10 @@
     feed:undefined
     redisClient:undefined

-    constructor: (app) ->
+    constructor: (@app) ->
         @startPublishingToRedis()

-        app.compound.server.on 'close', =>
+        @app.compound.server.on 'close', =>
             @stopListening()
             @redisClient.end() if @redisClient?

@@ -21,7 +21,7 @@
         @feed = db.changes since:'now'
         @feed.on 'change', @_onChange
         @feed.on 'error', (err) =>
-            compound.logger.write "error occured with feed : #{err.stack}"
+            @app.compound.logger.write "error occured with feed : #{err.stack}"
             @stopListening()

         @db = db
@@ -40,12 +40,12 @@
     startPublishingToRedis: () ->
         redis = require('redis')
         @redisClient = redis.createClient REDIS_PORT, REDIS_HOST,
-            max_attempts : 1
-        @redisClient.on "error", (err) ->
-            compound.logger.write "Failled to connect to redis : #{err.stack}"
-            compound.logger.write "Everything else should work as expected"
-        @redisClient.on "connect", ->
-            compound.logger.write "Begins publishing changes to redis"
+            max_attempts: 1
+        @redisClient.on "error", (err) =>
+            @app.compound.logger.write "Failled to connect to redis : #{err.stack}"
+            @app.compound.logger.write "Everything else should work as expected"
+        @redisClient.on "connect", =>
+            @app.compound.logger.write "Begins publishing changes to redis"

     publish: (event, id) => @_publish(event, id)

@@ -65,7 +65,7 @@
             else 'update'

             @db.get change.id, (err, doc) =>
-                compound.logger.write err if err?
+                @app.compound.logger.write err if err?
                 doctype = doc?.docType?.toLowerCase()
                 doctype ?= 'null'
                 @_publish "#{doctype}.#{operation}", doc._id


Fix callback in renameRoutes

Fix callback in renameRoutes

--- server/models/template.coffee
+++ server/models/template.coffee
@@ -35,8 +35,5 @@
   makePrimary(@primary, next)

 Template.statics.renameRoutes = (oldName, newName, callback) ->
-  Route.update({ template: oldName }, { template: newName }, (err, n) ->
-    callback(err)
-  )
-
+  Route.update({ template: oldName }, { template: newName }, callback)
 module.exports = db.model('Template', Template)


Ensure Column Is Set Correctly

Ensure Column Is Set Correctly

--- lib/gobuild.coffee
+++ lib/gobuild.coffee
@@ -71,7 +71,7 @@
       files = fs.readdirSync(fileDir)
     else
       output = '.go-plus-syntax-check'
-      outputPath = path.join(@tempDir, output + go.exe)
+      outputPath = path.normalize(path.join(@tempDir, output + go.exe))
       args = ['build', '-o', outputPath, '.']
     cmd = go.executable
     done = (exitcode, stdout, stderr, messages) =>
@@ -116,7 +116,7 @@
             file = path.join(cwd, matchLine[5])

         message = switch
-          when matchLine[4]?
+          when matchLine[8]?
             file: file
             line: matchLine[6]
             column: matchLine[8]


Commenting out live-update of monthly and yearly figures

Nice but might be a bit of overkill

--- views/home.coffee
+++ views/home.coffee
@@ -17,13 +17,13 @@
                                 #console.log document.URL
                                 $('#difference').load('/difference')

-                                $('#shared-balance-' + year + '-' + month).load('/monthly/' + year + '/' + month + '/shared_balance')
-                                $('#shared-income-' + year + '-' + month).load('/monthly/' + year + '/' + month + '/shared_income')
-                                $('#shared-expense-' + year + '-' + month).load('/monthly/' + year + '/' + month + '/shared_expense')
+                                # $('#shared-balance-' + year + '-' + month).load('/monthly/' + year + '/' + month + '/shared_balance')
+                                # $('#shared-income-' + year + '-' + month).load('/monthly/' + year + '/' + month + '/shared_income')
+                                # $('#shared-expense-' + year + '-' + month).load('/monthly/' + year + '/' + month + '/shared_expense')

-                                $('#yearly-shared-balance-' + year).load('/yearly/' + year + '/shared_balance')
-                                $('#yearly-shared-income-' + year).load('/yearly/' + year + '/shared_income')
-                                $('#yearly-shared-expense-' + year).load('/yearly/' + year + '/shared_expense')
+                                # $('#yearly-shared-balance-' + year).load('/yearly/' + year + '/shared_balance')
+                                # $('#yearly-shared-income-' + year).load('/yearly/' + year + '/shared_income')
+                                # $('#yearly-shared-expense-' + year).load('/yearly/' + year + '/shared_expense')

 $ ->
         bindSharedIcons()


Update# add test for Batman.I18N apply variable after get translation

--- tests/batman/extras/i18n_test.coffee
+++ tests/batman/extras/i18n_test.coffee
@@ -118,6 +118,11 @@
     equal node.childNodes[0].innerHTML, "this kind of defeats the purpose"
     QUnit.start()

+asyncTest "it should apply keypath value after get translation", ->
+  viewHelpers.render '

', false, {grapefruits: {count: 10}}, (node) ->
+    equal node.childNodes[0].innerHTML, "10 pamplemouses"
+    QUnit.start()
+
 asyncTest "it should look up keys in the translations under t", ->
   viewHelpers.render '

', false, {}, (node) ->
     equal node.childNodes[0].innerHTML, "pamplemouse", 't has been added to the default render stack'


Updating ingress-map

Updating ingress-map

It seems like the google maps integration is working.  Just need to
figure out how to properly zoom into the correct level.

--- scripts/ingress-map.coffee
+++ scripts/ingress-map.coffee
@@ -14,8 +14,8 @@
       msg.send "Please enter your Google API key in the environment variable HUBOT_GOOGLE_API_KEY."

     geocodeMe msg, query, (text) ->
-      msg.reply text
-    #msg.reply "https://www.ingress.com/intel?ll=36.066168,-86.928635&z=12"
+      #msg.reply text
+      msg.reply "https://www.ingress.com/intel?ll=" + text + "&z=12"

 geocodeMe = (msg, query, cb) ->
   msg.http("https://maps.googleapis.com/maps/api/geocode/json")
@@ -29,4 +29,5 @@
       return cb "No idea. Tried using a map? https://maps.google.com/" unless response.results?.length

       location = response.results[0].geometry.location.lat + "," + response.results[0].geometry.location.lng
-      cb "That's somewhere around " + location + " - https://maps.google.com/maps?q=" + location
+      #cb "That's somewhere around " + location + " - https://maps.google.com/maps?q=" + location
+      cb location


cluster support for loadbalancer

cluster support for loadbalancer

--- server/lib/server/index.coffee
+++ server/lib/server/index.coffee
@@ -25,6 +25,9 @@
     after: "non-overlapping, random, 3 digits prime-number of minutes"
     middleware : (name,callback) -> koding.disconnect callback
     middlewareTimeout : 5000
+  mixpanel:
+    key : KONFIG.mixpanel.key
+
 # if webPort is 3002
 #   foo = []
 #   do bar = ->
@@ -233,4 +236,4 @@

 app.listen webPort

-console.log 'Koding Webserver running ', "http://localhost:#{webPort} pid:#{process.pid}"
+console.log '[WEBSERVER] running ', "http://localhost:#{webPort} pid:#{process.pid}"


Fix layout

Fix layout

--- views/layout.cjsx
+++ views/layout.cjsx
@@ -41,5 +41,5 @@
   window._layout.unload()
   delete require.cache[require.resolve("./layout.#{layout}")]
   {layout} = e.detail
+  changeBounds()
   window._layout = require "./layout.#{layout}"
-  changeBounds()


Allow Literate CoffeeScript

Allow Literate CoffeeScript

--- plugins/webpack/webpack.coffee
+++ plugins/webpack/webpack.coffee
@@ -17,8 +17,11 @@
           coffee:
             test: /[.]coffee$/
             loader: "coffee-loader"
+          litcoffee:
+            test: /[.](litcoffee|coffee[.]md)$/
+            loader: "coffee-loader?literate"
       resolve:
-        extensions: ["", ".js", ".coffee"]
+        extensions: ["", ".js", ".coffee", ".litcoffee", ".coffee.md"]
       plugins: values
         minimize: new webpack.optimize.UglifyJsPlugin
         reorder: new webpack.optimize.OccurenceOrderPlugin


locals cleanup in progress

locals cleanup in progress

--- web/locals.coffee
+++ web/locals.coffee
@@ -1,50 +1,61 @@
-# Helpers, i.e. locals for this express.js app.
+# Helpers, i.e. the locals for this Express app.

 _ = require 'underscore'

+# Categories for project links.
+categories =
+  [ { id: "docs" }
+  , { id: "source" }
+  , { id: "c9" }
+  , { id: "issues" }
+  , { id: "tracker" }
+  , { id: "package" }
+  ]
+
+# Project customization by category plus possibly with some extra configuration.
+# Use a key, false to hide something, or full url is ok too.
+projects =
+  terra:
+    docs: false
+    tracker: "265847"
+    c9: false
+  upon:
+    issues: true
+    tracker: "265847"
+  archai:
+    issues: true
+    tracker: "265847"
+  eden:
+    tracker: "203533"
+  precious:
+    issues: true
+    tracker: "203533"
+  there:
+    tracker: "203533"
+  sin:
+    tracker: "203533"
+    package: "gravity"
+    c9: false
+  pi:
+    org: "astropi"
+    project: "astropi"
+    docs: "https://github.com/astropi/astropi#readme"
+    issues: true
+    tracker: "265847"
+    c9: false
+  astrolin:
+    issues: true
+    tracker: "265847"
+
+
 module.exports =

-  keys: (a) ->
-    _.keys(a)
+  keys: (o) -> _.keys(o)

-  cats: ["docs", "source", "c9", "issues", "tracker", "package"]
+  cats: _.pluck categories, "id"

-  # = key, false (hides it), or full url
-  projects:
-    terra:
-      docs: false
-      tracker: "265847"
-      c9: false
-    upon:
-      issues: true
-      tracker: "265847"
-    archai:
-      issues: true
-      tracker: "265847"
-    eden:
-      tracker: "203533"
-    precious:
-      issues: true
-      tracker: "203533"
-    there:
-      tracker: "203533"
-    sin:
-      tracker: "203533"
-      package: "gravity"
-      c9: false
-    pi:
-      org: "astropi"
-      project: "astropi"
-      docs: "https://github.com/astropi/astropi#readme"
-      issues: true
-      tracker: "265847"
-      c9: false
-    astrolin:
-      issues: true
-      tracker: "265847"
+  projects: projects

-  # TODO: w/o a view?
-  projectKeys: -> JSON.stringify { projects: _.keys this.projects }

   # Project links
   linkage: (project, details) ->
@@ -95,6 +106,7 @@
               links[key] = "#{ghpages}#{details[key]}"
     links

+
   # Category links across projects (a little bit sloppy, but no big deal)
   catLinks: (category) ->
     links = {}


fix upstart: use absolute path for SSL certs instead of relative

--- web_server.coffee
+++ web_server.coffee
@@ -4,8 +4,8 @@
 port_number = 3000

 app = express.createServer(
-  key: fs.readFileSync("certs/node-im.key")
-  cert: fs.readFileSync("certs/node-im.crt")
+  key: fs.readFileSync("#{__dirname}/certs/node-im.key")
+  cert: fs.readFileSync("#{__dirname}/certs/node-im.crt")
 )

 app.configure(() ->


Updated atom.io configuration

Updated atom.io configuration

--- config.cson
+++ config.cson
@@ -24,7 +24,7 @@
     ruby:
       beautify_on_save: true
   "autocomplete-java":
-    classpathFilePath: ".atomclasspath"
+    classpathFilePath: ".atom-classpath"
   core:
     closeDeletedFileTabs: true
     followSymlinks: false


Disabled atomic Emacs; too many conflicts with built-in keys

--- config.cson
+++ config.cson
@@ -7,6 +7,7 @@
       "notebook"
       "language-gfm"
       "wrap-guide"
+      "atomic-emacs"
     ]
     themes: [
       "one-dark-ui"


Only use native time & date pickers on touch devices.

--- web/js/views/search_view.coffee
+++ web/js/views/search_view.coffee
@@ -48,11 +48,11 @@
     initDateTimePickers: (date) ->
       date = @initializationTime if date is 'now'
       $('#time').val(Utils.formatTimeForHumans(date))
-      unless Modernizr.inputtypes.time
+      unless Modernizr.inputtypes.time and Modernizr.touch
         $('#time').timepicker(defaultTime: 'value', showMeridian: false)
       formattedDate = Utils.formatDateForHTML5Input(date)
       $('#date').val(formattedDate)
-      unless Modernizr.inputtypes.date
+      unless Modernizr.inputtypes.date and Modernizr.touch
         $('#date').datepicker(format: 'yyyy-mm-dd', weekStart: 1, language: Utils.language()).datepicker('setValue', formattedDate)

     searchRoutes: (event) ->
@@ -166,4 +166,4 @@
         @bookmarks = new Bookmarks()
         @bookmarksView = new BookmarksView(collection: @bookmarks, anchor: @to.$el, size: size)
           .show() # Need to make the element visible first, as it needs to calculate some widths
-          .render()+          .render()


patch fix

patch fix

--- lib/util/handlers/single.coffee
+++ lib/util/handlers/single.coffee
@@ -73,8 +73,8 @@
       return sendError res, "Not authorized", 401 unless perms.write is true

       for k,v of req.body when (k in getAllPaths(Model))
-        if mod.schema.paths[k].options?.authorize?
-          toCall = mod.schema.paths[k].options.authorize.bind mod
+        if mod.schema.tree[k]?.authorize?
+          toCall = mod.schema.tree[k].authorize.bind mod
           perms = toCall req
           return sendError res, "Not authorized", 401 unless perms.read is true
           return sendError res, "Not authorized", 401 unless perms.write is true


minor fix for watcher

minor fix for watcher

--- lib/util/package_watcher.coffee
+++ lib/util/package_watcher.coffee
@@ -14,8 +14,9 @@
   watch: =>
     _.each @naspi.option('runPkgs'), (runPkg) =>
       pkg = @getRunner().getPackage(runPkg.pkg)
+      pkg.setEnv({ runPkg: runPkg })

-      _.each pkg.getWatchConfigs(runPkg), (watchConfig) =>
+      _.each pkg.getWatchConfigs(), (watchConfig) =>
         @watchConfig runPkg, watchConfig

   watchConfig: (runPkg, watchConfig) =>


Remove screen overlay from screen preloader.

--- src/core/screen.coffee
+++ src/core/screen.coffee
@@ -130,7 +130,6 @@
         items      : Preloader.getImage("images/items.png")
         ui         : Preloader.getImage("images/ui.png")
     }
-    @screen = Preloader.getImage("images/screen" + Screen.SCALE + ".png")
     Screen.CENTER_OFFSET = Math.floor(Screen.WIN_SIZE / 2);

   clear: =>


Remove trailing whitespace

Remove trailing whitespace

--- src/core/shapes.coffee
+++ src/core/shapes.coffee
@@ -152,7 +152,7 @@
   fromJSON: (data) -> createShape('Line', data)

-linePathFuncs =
+linePathFuncs =
   constructor: (args={}) ->
     points = args.points or []
     @order = args.order or 3
@@ -288,7 +288,7 @@
     @color = args.color or 'black'
     @font  = args.font or '18px sans-serif'
     @boundingBoxHeight = 0 # set by random shit; double ugh
-  draw: (ctx) ->
+  draw: (ctx) ->
     ctx.font  = @font
     ctx.fillStyle = @color
     ctx.fillText(@text, @x, @y)


fix bug in addRootNode

fix bug in addRootNode

--- src/core/sphere.coffee
+++ src/core/sphere.coffee
@@ -27,7 +27,7 @@
         name: predicate

   addRootNode: (attrs) ->
-    @rootNode = addNode attrs
+    @rootNode = @addNode attrs
     @rootNode

   addNode: (attrs) ->


Cleanup.

Cleanup.

--- server/routes/index.coffee
+++ server/routes/index.coffee
@@ -10,9 +10,6 @@
 # Favicon.
 iconPath = path.resolve __dirname + '/../../client/assets/favicon.ico'
 iconStat = fs.statSync iconPath
-
-# Sitemap.xml.
-sitemap = path.resolve __dirname + '/../../client/assets/sitemap.xml'

 # Robots.txt.
 robots = path.resolve __dirname + '/../../client/assets/robots.txt'


support other language

support other language

support Python, Coffee, Rubu and Lua

--- tools/concat-tool/concat-tool.coffee
+++ tools/concat-tool/concat-tool.coffee
@@ -6,34 +6,42 @@
 configFile = 'concat-tool.json'

 concatVersion = (verName) ->
-    filename = verName + config.ext
-    console.log 'Processing: ' + filename + ' ...'
+	filename = verName + config.ext
+	console.log 'Processing: ' + filename + ' ...'

-    text = '// ' + filename + '\n'
-    text += '// Generated: ' + new Date().toLocaleString() + '\n\n'
-    for fname in config.versions[verName]
-        fname = fname.trim()
-        if fname.length > 0
-            text += '// File: ' + fname + config.ext + '\n\n'
-            text += fs.readFileSync (path.join config.src, fname + config.ext), "utf-8"
-            text += '\n'
-    fs.writeFileSync (path.join config.des, filename), text, { flag: "w" }
+	text = commentMark + ' ' + filename + '\n'
+	text += commentMark + ' Generated: ' + new Date().toLocaleString() + '\n\n'
+	for fname in config.versions[verName]
+		fname = fname.trim()
+		if fname.length > 0
+			text += commentMark + ' File: ' + fname + config.ext + '\n\n'
+			text += fs.readFileSync (path.join config.src, fname + config.ext), "utf-8"
+			text += '\n'
+	fs.writeFileSync (path.join config.des, filename), text, {flag: "w"}

 configFile = path.join __dirname, configFile
 if not fs.existsSync configFile
-    console.log "Error: config file not found: " + configFile
-    return
+	console.log "Error: config file not found: " + configFile
+	return

 config = JSON.parse (fs.readFileSync configFile, 'utf-8')

+commentMark = switch config.ext.toLowerCase()
+	when '.coffee', '.py', '.rb' # CoffeeScript, Python, Ruby
+		'#'
+	when '.lua' # Lua
+		'--'
+	else # JavaScript
+		'//'
+
 if not fs.existsSync config.src
-    console.log "Error: source dir not exists: " + path.join __dirname, config.src
+	console.log "Error: source dir not exists: " + path.join __dirname, config.src
 else
-    verNames = Object.keys config.versions
-    console.log 'Contating started. \n' +
-        "There are #{verNames.length} versions: #{ verNames }"
+	verNames = Object.keys config.versions
+	console.log 'Contating started. \n' +
+			"There are #{verNames.length} versions: #{ verNames }"

-    fs.mkdirSync config.des unless fs.existsSync config.des
-    for verName in verNames
-        concatVersion verName
-    console.log 'Contating completed.'
+	fs.mkdirSync config.des unless fs.existsSync config.des
+	for verName in verNames
+		concatVersion verName
+	console.log 'Contating completed.'


Fix(?)

Fix(?)

--- core.coffee
+++ core.coffee
@@ -92,6 +92,7 @@
 					date = item.commit.author.date
 					return callback() unless item.author?
 					getUserOrCreateUser item.author.login, (err, user) ->
+						return callback() unless user?
 						db.Commit.findOneAndUpdate {sha: item.sha},
 							sha: item.sha
 							author: user._id


Prevent CoffeeLint from blowing up when package.json can't be parsed

Fixes AtomLinter/linter-coffeelint#27

--- src/configfinder.coffee
+++ src/configfinder.coffee
@@ -26,7 +26,7 @@
 # Possibly find CoffeeLint configuration within a package.json file.
 loadNpmConfig = (dir) ->
     fp = findFile("package.json", dir)
-    loadJSON(fp).coffeelintConfig  if fp
+    loadJSON(fp)?.coffeelintConfig  if fp

 # Parse a JSON file gracefully.
 loadJSON = (filename) ->


make sure to clear any background image on root element

--- oriDomi.coffee
+++ oriDomi.coffee
@@ -306,6 +306,7 @@
     @el.style.width = @width + 'px'
     @el.style.height = @height + 'px'
     @el.style.backgroundColor = 'transparent'
+    @el.style.backgroundImage = 'none'
     @el.style.border = 'none'
     @el.style.outline = 'none'
     @stages.left.style.display = 'block'


gradient testing method returns full css prop name

--- oriDomi.coffee
+++ oriDomi.coffee
@@ -26,14 +26,16 @@
   false

-testGradient = ->
+getGradientProp = ->
   for prefix in prefixList
-    dashed = "-#{ prefix.toLowerCase() }-"
-    testEl.style.backgroundImage = "#{ dashed }linear-gradient(left, #000, #fff)"
+    dashed = "-#{ prefix.toLowerCase() }-linear-gradient"
+    testEl.style.backgroundImage = "#{ dashed }(left, #000, #fff)"
     if testEl.style.backgroundImage.indexOf('gradient') isnt -1
       return dashed

-  ''
+  'linear-gradient'
+
+

 # one dimensional:
@@ -64,6 +66,7 @@
   !backfaceProp or !transformOriginProp or !transformStyleProp
     oriDomiSupport = false
     console?.warn 'oriDomi: Browser does not support oriDomi'
+css.gradientProp = getGradientProp()

 defaults =
@@ -350,7 +353,7 @@

   _getShaderGradient: (anchor) ->
-    "#{ gradientPrefix }linear-gradient(#{ anchor }, rgba(0, 0, 0, .5) 0%, rgba(255, 255, 255, .35) 100%)"
+    "#{ css.gradientProp }(#{ anchor }, rgba(0, 0, 0, .5) 0%, rgba(255, 255, 255, .35) 100%)"

   _showStage: (anchor) ->


use same method for adding and removing touch handlers

--- oridomi.coffee
+++ oridomi.coffee
@@ -480,20 +480,8 @@

     # Create an element to hold stages.
     @stageEl = document.createElement 'div'
-    # Array of event type pairs.
-    eventPairs = [['TouchStart', 'MouseDown'], ['TouchEnd', 'MouseUp'],
-                  ['TouchMove', 'MouseMove'], ['TouchLeave', 'MouseLeave']]
-    # Detect native `mouseleave` support.
-    mouseLeaveSupport = 'onmouseleave' of window
-    # Attach touch/drag event listeners in related pairs.
-    for eventPair in eventPairs
-      for eString in eventPair
-        unless eString is 'TouchLeave' and not mouseLeaveSupport
-          @stageEl.addEventListener eString.toLowerCase(), @['_on' + eventPair[0]], false
-        else
-          @stageEl.addEventListener 'mouseout', @['_onMouseOut'], false
-          break
-
+
+    # Enable touch events.
     @enableTouch() if @settings.touchEnabled

     # Append each stage to the target element.
@@ -757,6 +745,33 @@
   # Touch / Drag Event Handlers
   # ===========================

+  # Adds or removes handlers from the element based on the boolean argument given.
+  _setTouch: (toggle) ->
+    if toggle
+      return if @_touchEnabled
+      listenFn = 'addEventListener'
+      @_touchEnabled = true
+    else
+      return unless @_touchEnabled
+      listenFn = 'removeEventListener'
+      @_touchEnabled = false
+
+    @_setCursor()
+
+    # Array of event type pairs.
+    eventPairs = [['TouchStart', 'MouseDown'], ['TouchEnd', 'MouseUp'],
+                  ['TouchMove', 'MouseMove'], ['TouchLeave', 'MouseLeave']]
+    # Detect native `mouseleave` support.
+    mouseLeaveSupport = 'onmouseleave' of window
+    # Attach touch/drag event listeners in related pairs.
+    for eventPair in eventPairs
+      for eString in eventPair
+        unless eString is 'TouchLeave' and not mouseLeaveSupport
+          @stageEl[listenFn] eString.toLowerCase(), @['_on' + eventPair[0]], false
+        else
+          @stageEl[listenFn] 'mouseout', @['_onMouseOut'], false
+          break
+

   # This method is called when a finger or mouse button is pressed on the element.
   _onTouchStart: (e) =>
@@ -891,35 +906,27 @@
     # First restore the original element.
     @freeze =>
       # Remove event listeners.
-      @stageEl.removeEventListener 'touchstart', @_onTouchStart, false
-      @stageEl.removeEventListener 'mousedown', @_onTouchStart, false
-      @stageEl.removeEventListener 'touchend', @_onTouchEnd, false
-      @stageEl.removeEventListener 'mouseup', @_onTouchEnd, false
-
+      @_setTouch false
       # Remove the data reference if using jQuery.
       $.data @el, 'oriDomi', null if $
       # Remove the oriDomi element from the DOM.
       @el.innerHTML = @cleanEl.innerHTML
-
       # Reset original styles.
       changedKeys = ['padding', 'width', 'height', 'backgroundColor', 'backgroundImage', 'border', 'outline']
       @el.style[key] = @_elStyle[key] for key in changedKeys
-
       # Free up this instance for garbage collection.
       instances[instances.indexOf @] = null
       callback?()

-  # Enables touch events and sets cursor.
+  # Enables touch events.
   enableTouch: ->
-    @_touchEnabled = true
-    @_setCursor()
+    @_setTouch true

   # Disables touch events.
   disableTouch: ->
-    @_touchEnabled = false
-    @_setCursor()
+    @_setTouch false

   # oriDomi's most basic effect. Transforms the target like its namesake.


capitalize OriDomi

capitalize OriDomi

--- oridomi.coffee
+++ oridomi.coffee
@@ -1,4 +1,4 @@
-# # oriDomi
+# # OriDomi
 # ### Fold up the DOM like paper.
 # 0.3.0

@@ -12,9 +12,9 @@
 # Helper Functions
 # ================

-# Function used to warn the developer that the browser does not support oriDomi.
+# Function used to warn the developer that the browser does not support OriDomi.
 supportWarning = (prop) ->
-  console?.warn "oriDomi: Missing support for `#{ prop }`."
+  console?.warn "OriDomi: Missing support for `#{ prop }`."
   isSupported = false

@@ -124,12 +124,12 @@
 # =====

 # Set a reference to jQuery (or another `$`-aliased DOM library).
-# If it doesn't exist, set to null so oriDomi knows we are working without jQuery.
-# oriDomi doesn't require it to work, but offers a useful plugin bridge.
+# If it doesn't exist, set to null so OriDomi knows we are working without jQuery.
+# OriDomi doesn't require it to work, but offers a useful plugin bridge.
 $ = if (window.jQuery or window.$)?.data then window.$ else null

 # This variable is set to true and negated later if the browser does
-# not support oriDomi.
+# not support OriDomi.
 isSupported = true

 anchorList  = ['left', 'right', 'top', 'bottom']
@@ -167,7 +167,7 @@

 elClasses[k] = "#{ baseName }-#{ v }" for k, v of elClasses

-# A map of the CSS3 properties needed to support oriDomi, with shorthand names as keys.
+# A map of the CSS3 properties needed to support OriDomi, with shorthand names as keys.
 css = new ->
   @[key] = key for key in [
     'transform'
@@ -190,7 +190,7 @@
   for key, value of css
     css[key] = testProp value
     # If the returned value is false, warn the user that the browser doesn't support
-    # oriDomi, set `isSupported` to false and break out of the loop.
+    # OriDomi, set `isSupported` to false and break out of the loop.
     unless css[key]
       supportWarning value
       return
@@ -335,7 +335,7 @@
 # Defaults
 # ========

-# Object literal of oriDomi instance defaults.
+# Object literal of OriDomi instance defaults.
 defaults =
   # The number of vertical panels (for folding left or right).
   vPanels: 3
@@ -354,7 +354,7 @@
   # makes the element wrap around and pass through itself leading to some glitchy visuals.
   maxAngle: 90
   ripple: 0
-  # This CSS class is applied to elements that oriDomi has been invoked so they can be
+  # This CSS class is applied to elements that OriDomi has been invoked so they can be
   # easily targeted later if needed.
   oriDomiClass: 'oridomi'
   # This is a multiplier that determines the darkness of shading.
@@ -368,7 +368,7 @@
   # Coefficient of touch/drag action's distance delta. Higher numbers cause more movement.
   touchSensitivity: .25
   # Custom callbacks for touch/drag events. Each one is invoked with a relevant value so they can
-  # be used to manipulate objects outside of the oriDomi instance (e.g. sliding panels).
+  # be used to manipulate objects outside of the OriDomi instance (e.g. sliding panels).
   # x values are returned when folding left and right, y values for top and bottom.
   # These are empty functions by default.
   # Invoked with starting coordinate as first argument.
@@ -379,7 +379,7 @@
   touchEndCallback: noOp

-# oriDomi Prototype
+# OriDomi Prototype
 # =================

 class OriDomi
@@ -389,7 +389,7 @@
     return new OriDomi arguments... unless @ instanceof OriDomi
     @el = document.querySelector @el if typeof @el is 'string'
     unless @el and @el.nodeType is 1
-      console?.warn 'oriDomi: First argument must be a DOM element'
+      console?.warn 'OriDomi: First argument must be a DOM element'
       return

     @_settings = new ->
@@ -882,7 +882,7 @@
     @

-  # Disables oriDomi slicing by showing the original, untouched target element.
+  # Disables OriDomi slicing by showing the original, untouched target element.
   # This is useful for certain user interactions on the inner content.
   freeze: (callback) ->
     # Return if already frozen.
@@ -900,7 +900,7 @@
     @

-  # Restores the oriDomi version of the element for folding purposes.
+  # Restores the OriDomi version of the element for folding purposes.
   unfreeze: ->
     # Only unfreeze if already frozen.
     if @isFrozen
@@ -914,7 +914,7 @@
     @

-  # Removes the oriDomi element and restores the original element.
+  # Removes the OriDomi element and restores the original element.
   destroy: (callback) ->
     # First restore the original element.
     @freeze =>
@@ -922,7 +922,7 @@
       @_setTouch false
       # Remove the data reference if using jQuery.
       $.data @el, baseName, null if $
-      # Remove the oriDomi element from the DOM.
+      # Remove the OriDomi element from the DOM.
       @el.innerHTML = @_cloneEl.innerHTML
       # Reset original styles.
       @el.classList.remove elClasses.active
@@ -1004,7 +1004,7 @@
   # ==============

-  # oriDomi's most basic effect. Transforms the target like its namesake.
+  # OriDomi's most basic effect. Transforms the target like its namesake.
   accordion: prep (angle, anchor, options) ->
     # Loop through the panels in this stage.
     @_iterate anchor, (panel, i) =>
@@ -1138,7 +1138,7 @@
   @VERSION = '0.3.0'

-  # Externally check if oriDomi is supported by the browser.
+  # Externally check if OriDomi is supported by the browser.
   @isSupported = isSupported

@@ -1158,9 +1158,9 @@

 # Only create bridge if jQuery (or an imitation supporting `data()`) exists.
 return unless $
-# Attach an `oriDomi` method to `$`'s prototype.
+# Attach an `OriDomi` method to `$`'s prototype.
 $::oriDomi = (options) ->
-  # Return selection if oriDomi is unsupported by the browser.
+  # Return selection if OriDomi is unsupported by the browser.
   return @ unless isSupported

   # If `options` is a string, assume it's a method call.
@@ -1168,13 +1168,13 @@
     methodName = options
     # Check if method exists and warn if it doesn't.
     unless typeof (method = OriDomi::[methodName]) is 'function'
-      console?.warn "oriDomi: No such method `#{ methodName }`"
+      console?.warn "OriDomi: No such method `#{ methodName }`"
       return @

-    # Warn if oriDomi hasn't been initialized on this element.
+    # Warn if OriDomi hasn't been initialized on this element.
     unless instance = $.data @[0], baseName
-      console?.warn "oriDomi: Can't call #{ methodName }, oriDomi hasn't been initialized on this element"
+      console?.warn "OriDomi: Can't call #{ methodName }, OriDomi hasn't been initialized on this element"
       return @

     # Call the requested method with arguments.
@@ -1183,15 +1183,15 @@
     # Return selection.
     @

-  # If not calling a method, initialize oriDomi on the selection.
+  # If not calling a method, initialize OriDomi on the selection.
   else
     for el in @
-      # If the element in the selection already has an instance of oriDomi
+      # If the element in the selection already has an instance of OriDomi
       # attached to it, return the instance.
       if instance = $.data el, baseName
         return instance
       else
-        # Create an instance of oriDomi and attach it to the element.
+        # Create an instance of OriDomi and attach it to the element.
         $.data el, baseName, new OriDomi el, options

     # Return the selection.


more explicit support warnings

more explicit support warnings

--- oridomi.coffee
+++ oridomi.coffee
@@ -32,6 +32,12 @@
 # This variable is set to true and negated later if the browser does
 # not support oriDomi.
 oriDomiSupport = true
+
+# Function used to warn the developer that the browser does not support oriDomi.
+supportWarning = (prop) ->
+  if devMode
+    console.warn "oriDomi: Browser does not support oriDomi. Missing support for `#{ prop }`."
+    oriDomiSupport = false

 # Create a div for testing CSS3 properties.
 testEl = document.createElement 'div'
@@ -69,8 +75,7 @@
   # If the returned value is false, warn the user that the browser doesn't support
   # oriDomi, set `oriDomiSupport` to false, and break out of the loop.
   unless css[key]
-    console.warn 'oriDomi: Browser does not support oriDomi' if devMode
-    oriDomiSupport = false
+    supportWarning value
     break

 # CSS3 gradients are used for shading.


Update 673affc6b86636051fb73a9f1ad3050ef82714ab  to fix #31

--- lib/manager.coffee
+++ lib/manager.coffee
@@ -11,24 +11,17 @@
     if @lastCfgTime? and Date.now() - @lastCfgTime < 200
       return @config?
     @lastCfgTime = Date.now()
-    editor = atom.workspace.getActivePaneItem()
-    currentPath = editor?.buffer.file?.path
-    currentDir = path.dirname(currentPath)
-    if currentDir?
-      dirs = [currentDir]
-    else
-      dirs = []
-    for rootDir in dirs.concat(atom.project.getPaths())
-      for file in fs.readdirSync rootDir
-        if file is '.latexcfg'
-          try
-            filePath = path.join rootDir, file
-            fileContent = fs.readFileSync filePath, 'utf-8'
-            @config = JSON.parse fileContent
-            if @config.root?
-              @config.root = path.resolve rootDir, @config.root
-            return true
-          catch err
+    rootDir = atom.project.relativizePath(atom.workspace.getActiveTextEditor().getPath())[0]
+    for file in fs.readdirSync rootDir
+      if file is '.latexcfg'
+        try
+          filePath = path.join rootDir, file
+          fileContent = fs.readFileSync filePath, 'utf-8'
+          @config = JSON.parse fileContent
+          if @config.root?
+            @config.root = path.resolve rootDir, @config.root
+          return true
+        catch err
     return false

   isTexFile: (name) ->
@@ -57,10 +50,10 @@
       return true if @findMainSelfMagic()
       return true if @findMainSelf()

+    return true if @findMainConfig()
     if @latex.mainFile?
       return true

-    return true if @findMainConfig()
     return true if @findMainSelfMagic()
     return true if @findMainSelf()
     return true if @findMainAllRoot()


Added spaces after commas

Added spaces after commas

--- APIBlueprintGenerator.coffee
+++ APIBlueprintGenerator.coffee
@@ -27,7 +27,7 @@
     has_body = body.length > 0
     if has_body
       if is_json
-        body = JSON.stringify(JSON.parse(body),null,4)
+        body = JSON.stringify(JSON.parse(body), null, 4)
       body_indentation = '        '
       if has_headers
         body_indentation += '    '
@@ -64,7 +64,7 @@
     has_body = body.length > 0
     if has_body
       if is_json
-        body = JSON.stringify(JSON.parse(body),null,4)
+        body = JSON.stringify(JSON.parse(body), null, 4)
       body_indentation = '        '
       if has_headers
         body_indentation += '    '


Tweak random mutation test

Tweak random mutation test

Signed-off-by: Nathan Sobo <2e8aa918660411855c6d44d5bb2da677aa033255@github.com>

--- spec/buffer-layer-spec.coffee
+++ spec/buffer-layer-spec.coffee
@@ -86,20 +86,17 @@
       expect(source.getRecordedReads()).toEqual ["abc"]

   describe "randomized mutations", ->
-    [seed, random] = []
+    it "behaves as if it were reading and writing directly to the underlying layer", ->
+      for i in [0..30] by 1
+        seed = Date.now()
+        # seed = 1426552034823
+        random = new Random(seed)

-    beforeEach ->
-      seed = Date.now()
-      # seed = 1426552034823
-      random = new Random(seed)
+        oldContent = "abcdefghijklmnopqrstuvwxyz"
+        source = new StringLayer(oldContent)
+        buffer = new BufferLayer(source)
+        reference = new StringLayer(oldContent)

-    it "behaves as if it were reading and writing directly to the underlying layer", ->
-      oldContent = "abcdefghijklmnopqrstuvwxyz"
-      source = new StringLayer(oldContent)
-      buffer = new BufferLayer(source)
-      reference = new StringLayer(oldContent)
-
-      for i in [0..30] by 1
         for j in [0..10] by 1
           currentContent = buffer.slice()
           newContentLength = random(20)
@@ -111,7 +108,7 @@
           extent = Point(0, endColumn - startColumn)

           # console.log buffer.slice()
-          # console.log buffer.splice(#{start}, #{extent}, #{newContent})
+          # console.log "buffer.splice(#{start}, #{extent}, #{newContent})"

           reference.splice(start, extent, newContent)
           buffer.splice(start, extent, newContent)


FIX: Update task ilo alignment editor template path

--- src/app/tasks/task-ilo-alignment/task-ilo-alignment-editor/task-ilo-alignment-editor.coffee
+++ src/app/tasks/task-ilo-alignment/task-ilo-alignment-editor/task-ilo-alignment-editor.coffee
@@ -3,7 +3,7 @@
 .directive('taskIloAlignmentEditor', ->
   replace: true
   restrict: 'E'
-  templateUrl: 'units/partials/templates/unit-outcome-alignment.tpl.html'
+  templateUrl: 'tasks/task-ilo-alignment/task-ilo-alignment-editor/task-ilo-alignment-editor.tpl.html'
   scope:
     unit: "="
     project: "=?"


changing utils for markdown support (htmlencoded form data)

--- core/utils.coffee
+++ core/utils.coffee
@@ -85,23 +85,20 @@
     value.replace /<(?:.|\n)*?>/gm, ''

   applyMarkdown: (text)->
-
     # problems with markdown so far:
-    # - clashes with some of the htmlentities in the sanitized properties
     # - links are broken due to textexpansions (images too i guess)
-
-
-    return null unless text
+    return null unless text
+
     marked.setOptions
       gfm: true
       pedantic: false
       sanitize: true
       highlight:->
+        # highlight wants a callback to fetch syntax highlighting
         null
-    log "applying markdown to ", text
-    text = text.replace /(
)/g,"\n"
-    text = text.replace /"/g,'"'
-    log "it's now", text
+
+    text = Encoder.htmlDecode text
+
     marked text

   applyLineBreaks: (text)->


utils: improve formatPlural

utils: improve formatPlural

Add an optional third argument showCount which can be used to suppress the count from the formatted output.  This can be useful in case you want to mark up the count differently than the incorporating sentence, e.g. <b>4</b> mice

--- core/utils.coffee
+++ core/utils.coffee
@@ -12,8 +12,18 @@
       if @[key] then throw new Error "#{key} is already registered"
       else @[key] = val

-  formatPlural:(count, noun)->
-    "#{count or 0} #{if count is 1 then noun else Inflector.pluralize noun}"
+  formatPlural:(count, noun, showCount = yes)->
+    """
+    #{
+      if showCount
+      then "#{count} " or 0
+      else ''
+    }#{
+      if count is 1
+      then noun
+      else Inflector.pluralize noun
+    }
+    """

   selectText:(element, selectionStart, selectionEnd)->
     doc   = document


Assert that resolved atom shell module paths exist

--- spec/module-cache-spec.coffee
+++ spec/module-cache-spec.coffee
@@ -14,6 +14,7 @@

     for builtinName, builtinPath of builtins
       expect(require.resolve(builtinName)).toBe builtinPath
+      expect(fs.isFileSync(require.resolve(builtinName)))

     expect(Module._findPath.callCount).toBe 0


Add search with regex option tests to SearchModel spec

--- spec/search-model-spec.coffee
+++ spec/search-model-spec.coffee
@@ -20,3 +20,14 @@
       expect(spy).toHaveBeenCalled()
       expect(spy.mostRecentCall.args[0]).toEqual subject
       expect(spy.mostRecentCall.args[1]).toEqual regex: subject.regex
+
+  describe "search() with options", ->
+    beforeEach ->
+    describe "regex option", ->
+      it 'returns regex matches when on', ->
+        subject.search('items.', regex: true)
+        expect(subject.regex.test('items;')).toEqual(true)
+
+      it 'returns only literal matches when off', ->
+        subject.search('items.', regex: false)
+        expect(subject.regex.test('items;')).toEqual(false)


atom.syntax -> atom.grammars

atom.syntax -> atom.grammars

--- spec/symbols-view-spec.coffee
+++ spec/symbols-view-spec.coffee
@@ -427,7 +427,7 @@

       runs ->
         atom.commands.dispatch(getEditorView(), "symbols-view:toggle-file-symbols")
-        atom.workspace.getActiveTextEditor().setGrammar(atom.syntax.grammarForScopeName('source.js'))
+        atom.workspace.getActiveTextEditor().setGrammar(atom.grammars.grammarForScopeName('source.js'))
         atom.commands.dispatch(getEditorView(), "symbols-view:toggle-file-symbols")
         symbolsView = $(getWorkspaceView()).find('.symbols-view').view()
         expect(symbolsView.loading).toBeVisible()


Fix path normalization

Fix path normalization

--- services/web/public/coffee/app/ide/pdf/controllers/PdfController.coffee
+++ services/web/public/coffee/app/ide/pdf/controllers/PdfController.coffee
@@ -89,7 +89,7 @@

 			rootDocDirname = ide.fileTreeManager.getRootDocDirname()
 			if rootDocDirname?
-				path = path.replace(/^\.\//, rootDocDirname)
+				path = path.replace(/^\.\//, rootDocDirname + "/")

 			return path


fixing problem when there is empty collection on histogram sorting

Former-commit-id: c54ccdb9b00ca6a3e1befeeece27763a3e45126c [formerly 3db2857f645eef53861c5029c07ecdccdeccce90] [formerly a7c91f2dd15ab409557a4b5562d34a0cfb7ef10e [formerly a7c91f2dd15ab409557a4b5562d34a0cfb7ef10e [formerly b81c0c30380c2c1258b9efea108ce7d5a791e621]]]
Former-commit-id: cbe8a61c241cc5f0c695e18e380fd4f4de00cd1e [formerly a56fa2e0558c2137f5a86c5896baf4f39bd3ad30]
Former-commit-id: 0432af5006a66837bb0f530ce06b2242d798026a
Former-commit-id: b8f0ab9948055620bedcea5fd3e0a2d7de5a3936

--- app/assets/javascripts/backbone/apps/franklin/proposal/aggregate/aggregate_controller.coffee
+++ app/assets/javascripts/backbone/apps/franklin/proposal/aggregate/aggregate_controller.coffee
@@ -43,15 +43,16 @@
             fld = if segment == 'all' then 'score' else "score_stance_group_#{segment}"
             reasons_layout.updateHeader segment
             _.each [aggregated_pros, aggregated_cons], (collection, idx) =>
-              collection.setSorting fld, 1
-              collection.fullCollection.sort()
+              if collection.length > 0
+                collection.setSorting fld, 1
+                collection.fullCollection.sort()

-              if idx of @removed_points
-                collection.fullCollection.add @removed_points[idx]
+                if idx of @removed_points
+                  collection.fullCollection.add @removed_points[idx]

-              @removed_points[idx] = collection.fullCollection.filter( (point) -> !point.get(fld) || point.get(fld) == 0 )
+                @removed_points[idx] = collection.fullCollection.filter( (point) -> !point.get(fld) || point.get(fld) == 0 )

-              collection.fullCollection.remove @removed_points[idx]
+                collection.fullCollection.remove @removed_points[idx]
             @pros_controller.layout.render()
             @cons_controller.layout.render()


Changed bullet speed and lifetime

Changed bullet speed and lifetime

--- bullet.coffee
+++ bullet.coffee
@@ -15,8 +15,8 @@
     defaultOptions =
       position: [Math.random(), Math.random()]
       velocity: [0.08, 0.09]
-      maxLifeTime: 1
-      initialSpeed: 0.07
+      maxLifeTime: 3
+      initialSpeed: 0.5
       direction: null
       shipId: 0
       active: true


Change pin

Change pin

--- buzzer.coffee
+++ buzzer.coffee
@@ -18,7 +18,7 @@
       connection:
         name: 'raspi', adaptor: 'raspi'
       device:
-        name: 'servo', driver: 'servo', pin: 3,
+        name: 'servo', driver: 'servo', pin: 7,
       work: ( pi ) =>
         @pi = pi
         @close()
@@ -33,10 +33,9 @@
       if @lastOpened isnt data.last_open
         @lastOpened = data.last_open
       else
-        console.log('Already opened')
+        console.log('Already opened for this request')
         return

-    console.log('Trying to open')
     time = Number(length)
     if isNaN(time)
       time = @defaultTime


Cleanup CMIV initialization

Cleanup CMIV initialization

--- lib/motions.coffee
+++ lib/motions.coffee
@@ -281,10 +281,10 @@
     super(count)

 class Search extends Motion
+  # We're overwriting the constructor to use the editor view instead
+  # of the editor, as we'll need to attach a CMIV to it.
   constructor: (@editorView, @state) ->
     super(@editorView.editor, @state)
-
-  initialize: =>
     @historyIndex = -1
     @view = new VimCommandModeInputView(@, class: 'search')
     @editor.commandModeInputView = @view


keep project config

keep project config

--- lib/atom-ternjs-config.coffee
+++ lib/atom-ternjs-config.coffee
@@ -5,9 +5,9 @@
 class Config

   configView: null
-  config: []
+  config: null
+  projectConfig: null
   manager: null
-  projectConfig: null

   constructor: (manager, state = {}) ->
     @manager = manager
@@ -58,12 +58,12 @@
   gatherData: ->
     configStub = @getContent('../tern-config.json', false)
     return unless configStub
-    localConfig = @getContent('/.tern-project', true)
-    if localConfig
-      localConfig = @prepareLibs(localConfig, configStub)
-      for plugin of localConfig.plugins
-        localConfig.plugins[plugin]?.active = true
-      @config = @mergeConfigObjects(configStub, localConfig)
+    @projectConfig = @config = @getContent('/.tern-project', true)
+    if @projectConfig
+      @config = @prepareLibs(@config, configStub)
+      for plugin of @config.plugins
+        @config.plugins[plugin]?.active = true
+      @config = @mergeConfigObjects(configStub, @config)
     else
       @config = configStub
     @configView.buildOptionsMarkup()


cleanup

cleanup

--- lib/autohide-tree-view.coffee
+++ lib/autohide-tree-view.coffee
@@ -71,7 +71,8 @@
     {pushEditor} = @conf

     # wait until the tree view package is activated
-    atom.packages.activatePackage('tree-view').then (treeViewPkg) =>
+    atom.packages.activatePackage 'tree-view'
+    .then (treeViewPkg) =>
       @registerTreeView treeViewPkg
       @handleEvents()
       # start with pushEditor = true, we'll change it back later
@@ -125,20 +126,18 @@
       'autohide-tree-view:toggle': => @toggle()

     # add listeners for mouse events
-    @disposables.add atom.config.observe 'autohide-tree-view.showOn', do =>
-      disposables = null
-
-      (value) =>
-        disposables?.dispose()
-        @disposables.add disposables = new SubAtom()
-        if value.match 'hover'
-          disposables.add 'atom-workspace', 'mouseenter', '.tree-view-resizer.autohide-hover', => @show()
-          disposables.add 'atom-workspace', 'mouseleave', '.tree-view-resizer.autohide-hover', => @hide()
-        if value.match 'click'
-          disposables.add 'atom-workspace', 'click', '.tree-view-resizer', (event) => @toggle value is 'click'
-          disposables.add '.tree-view', 'blur', =>
-            @clearFocusedElement()
-            @hide 0
+    mouseEventDisposables = null
+    @disposables.add atom.config.observe 'autohide-tree-view.showOn', (value) =>
+      mouseEventDisposables?.dispose()
+      @disposables.add mouseEventDisposables = new SubAtom()
+      if value.match 'hover'
+        mouseEventDisposables.add 'atom-workspace', 'mouseenter', '.tree-view-resizer.autohide-hover', => @show()
+        mouseEventDisposables.add 'atom-workspace', 'mouseleave', '.tree-view-resizer.autohide-hover', => @hide()
+      if value.match 'click'
+        mouseEventDisposables.add 'atom-workspace', 'click', '.tree-view-resizer', (event) => @toggle value is 'click'
+        mouseEventDisposables.add '.tree-view', 'blur', =>
+          @clearFocusedElement()
+          @hide 0

     # disable the tree view from showing during a selection
     @disposables.add 'atom-text-editor', 'mousedown', => @disableHoverEvents()
@@ -197,7 +196,8 @@
     @disableHoverEvents() if disableHoverEvents
     @storeFocusedElement()
     @treeView.scroller[0].style.display = ''
-    @animate(@treeView.list[0].clientWidth, delay).then (finished) =>
+    @animate @treeView.list[0].clientWidth, delay
+    .then (finished) =>
       @visible = true
       @treeView.focus() if finished

@@ -205,7 +205,8 @@
     @visible = false
     @enableHoverEvents()
     @recoverFocus()
-    @animate(@conf.hiddenWidth, delay).then (finished) =>
+    @animate @conf.hiddenWidth, delay
+    .then (finished) =>
       @treeView.scroller[0].style.display = 'none' if finished

   toggle: (disableHoverEvents = true) ->
@@ -213,7 +214,7 @@

   resize: ->
     promiseNextTick.then() =>
-      if @visible then @show(0) else @hide(0)
+      if @visible then @show 0  else @hide 0
     .catch error

   storeFocusedElement: ->
@@ -241,7 +242,7 @@
   # resolves true if animation finished, false if animation cancelled
   animate: (targetWidth, delay) ->
     initialWidth = @treeViewEl.clientWidth
-    duration = Math.abs(targetWidth - initialWidth) / (@conf.animationSpeed or Infinity)
+    duration = Math.abs targetWidth - initialWidth / (@conf.animationSpeed or Infinity)

     if @currentAnimation? and @currentAnimation.playState isnt 'finished'
       @currentAnimation.cancel()


function -> work

function -> work

Former-commit-id: 16153c1eed7bfdfb26dabbe38fcb4a3bfd768b80 [formerly c06c465af8b227fffe452a6e2fceeb717d0771a2] [formerly 1499a5d10f1937594252f8561f8fa6c727ff5cf7 [formerly 07bc0fff5395868c7ba56935b2d04fe277bceece]] [formerly 0ca27aa525d600cf3c51b5b7501fdd1c642ccb39 [formerly b9b3907d8603c6261214386de789ebe1c84b2745] [formerly cdf1c61264701be48d5459500fd44308234f3a27 [formerly cdf1c61264701be48d5459500fd44308234f3a27 [formerly 7e52394bd22f6a8b69d402b393130982c5eb299e]]]]
Former-commit-id: 59c5b4a4da3a8343578b8b51b5ac560411aa1fd7 [formerly 4069830679d8da5a4424f5c13cd4b3755cc8ecba] [formerly ffc004fb97423546ad526a643d562f32a513611f [formerly cc24b7678e06a8933f8237933ca42e409186aed4]]
Former-commit-id: 9693fe3947acceb6ad259f37370602f227d92544 [formerly 3c00697d3245488c4ae5ddd9a936a2e3f097c18e]
Former-commit-id: 00071a0fb3362f6a3ab01020e7994872a8f6a63f
Former-commit-id: 802326426f1645143821711f6dc0fb8a0eaa6863

--- @client/saas_landing_page.coffee
+++ @client/saas_landing_page.coffee
@@ -492,7 +492,7 @@
       marginTop: if ui.frame == 'laptop' then 30 else 60

     H1 style: h1,
-      'The first forum to function better'
+      'The first forum that works better'
       BR null,
       'when more people participate'


Fixed bug

Fixed bug

--- cs_app/app.coffee
+++ cs_app/app.coffee
@@ -213,7 +213,7 @@
     functions.writePasses _.filter(functions.getPasses(), (p) -> p.time > new Date().getTime() - 604800000)
     functions.writeTarContents _.filter(functions.getTarContents(), (c) -> fs.existsSync(settings.downloadDir + c.filename))
     if settings.downloadExpireDays > 0
-      functions.writeUserNZBs _.filter(functions.getUserNZBs(), (n) -> n.time > new Date().getTime() - 604800000)
+      functions.writeUserNZBs _.filter(functions.getUserNZBs(), (n) -> n.time > new Date().getTime() - (settings.downloadExpireDays * 86400000))
   , 86400
 else
   settings.setup()


Fix another subscription leakage associated with theme manager specs

--- spec/theme-manager-spec.coffee
+++ spec/theme-manager-spec.coffee
@@ -286,5 +286,10 @@
       runs ->
         spyOn(console, 'warn')
         expect(-> atom.config.set('core.themes', ['atom-light-ui', 'theme-really-does-not-exist'])).not.toThrow()
+
+      waitsFor (done) ->
+        themeManager.once 'reloaded', done
+
+      runs ->
         expect(console.warn.callCount).toBe 1
         expect(console.warn.argsForCall[0][0].length).toBeGreaterThan 0


Remove superfluous change to controller state from within samus controller action system

--- src/javascript/game/entity/samus/systems/samus_controller_action.coffee
+++ src/javascript/game/entity/samus/systems/samus_controller_action.coffee
@@ -1,7 +1,7 @@

 module.exports =
   config:
-    filters: ['samus','short_beam','controller']
+    filters: ['samus','controller']

   update: (comps,input,u) ->
     samus = comps.get('samus')
@@ -55,8 +55,5 @@
       .set('action', action))

-     # TODO is this really necessary? Because this is kinda jank, updating the controller states like this...
-    if samus.get('motion') == 'falling'
-      u.update(comps.get('controller').setIn(['states','jump'], false))


Use a times symbol, not an x

Use a times symbol, not an x

--- src/historystep.coffee
+++ src/historystep.coffee
@@ -18,7 +18,7 @@
         $('#history').prepend(object)
         prevElementCount = 0
       prevElementCount += 1
-      object.text "#{prevElementCount} x #{type} "
+      object.text "#{prevElementCount} × #{type} "
       restoreLink = $('<a href="#">')
       restoreLink.text 'restore'
       do (elPosition) ->


do some changes to @formatShellCmd

do some changes to @formatShellCmd

--- lib/linter-js-standard.coffee
+++ lib/linter-js-standard.coffee
@@ -1,6 +1,7 @@
 linterPath = atom.packages.getLoadedPackage("linter").path
 Linter = require "#{linterPath}/lib/linter"
 {findFile, warn} = require "#{linterPath}/lib/utils"
+fs = require 'fs'

 class LinterJsStandard extends Linter

@@ -30,12 +31,27 @@
   constructor: (editor) ->
     super(editor)

-    atom.config.observe 'linter-js-standard.jsStandardExecutablePath', @formatShellCmd
+    atom.config.observe 'linter-js-standard.jsStandardExecutablePath',
+      @formatShellCmd
+
     @cwd = null

-  formatShellCmd: =>
-    jshintExecutablePath = atom.config.get 'linter-js-standard.jsStandardExecutablePath'
-    @executablePath = "#{jshintExecutablePath}"
+  formatShellCmd: (standardPath) =>
+
+    ## If standard path
+    # isn't defined return early,
+    # try next time
+    if typeof standardPath == 'undefined'
+      return
+
+    executionPath =
+      standardPath + '/cmd.js'
+
+    if fs.existsSync executionPath
+      @executablePath = "#{standardPath}"
+    else
+      throw new Error 'Standard wasn\'t installed properly with linter-js-standard, please re-install the plugin.'
+

   formatMessage: (match) ->
     type = if match.error


improve open/close all relative files

improve open/close all relative files

--- lib/related.coffee
+++ lib/related.coffee
@@ -16,9 +16,24 @@
   currentFilePath.replace alloyRegExp, (match, p1, p2, p3, offset, string)->
     return "/#{alloyDirectoryMap[type]}/#{p2}.#{type}"

-related2ndPane = undefined
-related3rdPane = undefined
+getRelatedFilePath = (editorPath) ->
+  [isAlloy, alloyType, filename, fileExt] = editorPath.match(alloyRegExp) || []
+  isAppTss = /app\/styles\/app.tss$/.test editorPath; # TODO : make more advanced Detection
+  isAlloyJs = /app\/alloy.js$/.test editorPath; # TODO : make more advanced Detection
+
+  relatedFilePaths = []
+
+  if isAppTss
+    relatedFilePaths = [editorPath.replace('app/styles/app.tss','app/alloy.js')]
+  else if isAlloyJs
+    relatedFilePaths = [editorPath.replace('app/alloy.js','app/styles/app.tss')]
+  else if isAlloy
+    _.each alloyDirectoryMap, (folderName,ext)->
+      if ext!= fileExt
+        relatedFilePaths.push(getTargetPath(ext,editorPath));

+  relatedFilePaths
+
 module.exports =
   activate: ->
     atom.commands.add 'atom-workspace', 'titanium:openView': => @openFile('xml')
@@ -26,7 +41,7 @@
     atom.commands.add 'atom-workspace', 'titanium:openController': => @openFile('js')
     atom.commands.add 'atom-workspace', 'titanium:openAllRelatedFiles': => @openAllFiles()
     atom.commands.add 'atom-workspace', 'titanium:closeAllRelatedPanes': => @closeAllRelatedPanes()
-
+
   openFile: (type, options = {})->
     options.searchAllPanes = true
     atom.workspace.open getTargetPath(type), options
@@ -36,45 +51,39 @@
     previousActivePane = atom.workspace.getActivePane()
     return unless editor?

-    editorPath = editor.getPath()
-    [isAlloy, alloyType, filename, fileExt] = editorPath.match(alloyRegExp) || []
-    isAppTss = /app\/styles\/app.tss$/.test editorPath;
-    isAlloyJs = /app\/alloy.js$/.test editorPath;
+    # if number of panes is under 3, make more.
+    numberOfPanes = atom.workspace.getPanes().length;

-    relatedFilePaths = []
-    if isAppTss
-      relatedFilePaths = [editorPath.replace('app/styles/app.tss','app/alloy.js')]
-    else if isAlloyJs
-      relatedFilePaths = [editorPath.replace('app/alloy.js','app/styles/app.tss')]
-    else if isAlloy
-      _.each alloyDirectoryMap, (folderName,ext)->
-        if ext!= fileExt
-          relatedFilePaths.push(getTargetPath(ext,editor.getPath()));
-    else
-      return
+    while atom.workspace.getPanes().length<3
+      lastPane = _.last(atom.workspace.getPanes())
+      if atom.config.get('titanium-alloy.numberOfSplitPane')==2 and atom.workspace.getActivePane().length == 2
+        lastPane.splitDown()
+      else
+        lastPane.splitRight()
+
+    relatedFilePaths = getRelatedFilePath(editor.getPath())
+    return unless relatedFilePaths.length

+    panes = atom.workspace.getPanes()

-    if related2ndPane?.isAlive() != true
-      related2ndPane = atom.workspace.getActivePane().splitRight()
-    related2ndPane.activate();
-    atom.workspace.open(relatedFilePaths[0])
+    newPaneIdx = 0
+    for pane in panes
+      if pane != previousActivePane and relatedFilePaths[newPaneIdx]
+        pane.activate();
+        atom.workspace.open(relatedFilePaths[newPaneIdx++], {}).then( ->
+          previousActivePane.activate();
+        )
+
+  closeAllRelatedPanes: () ->
+    editor = atom.workspace.getActiveTextEditor()
+    relatedFilePaths = getRelatedFilePath(editor.getPath())
+    allEditors = atom.workspace.getTextEditors()

-    if relatedFilePaths[1]
-      if related3rdPane?.isAlive() != true
-        if atom.config.get('titanium-alloy.numberOfSplitPane')==2
-          related3rdPane = related2ndPane.splitDown()
-        else
-          related3rdPane = related2ndPane.splitRight()
-      related3rdPane.activate();
-      atom.workspace.open(relatedFilePaths[1]).then( ->
-        previousActivePane.activate();     # restore cursor focus
-      )
-
-  closeAllRelatedPanes: () ->
-    # if related2ndPane?.isAlive() == true
-    related2ndPane.destroy() if related2ndPane?.isAlive()
-
-    # if related3rdPane?.isAlive() == true
-    related3rdPane.destroy() if related3rdPane?.isAlive()
+    # find and close
+    for editor in allEditors
+      for path in relatedFilePaths
+        if path == editor.getPath()
+          editor.destroy()

   getTargetPath: getTargetPath
+  getRelatedFilePath : getRelatedFilePath


GM script: Show links as list

GM script: Show links as list

--- src-client/infolis.user.coffee
+++ src-client/infolis.user.coffee
@@ -1,5 +1,5 @@
 client = new InfolinkClient(
-	baseURI: 'http://localhost:3000'
+	baseURI: 'http://infolis.gesis.org/infolink'
 )

 $('head').append(
@@ -59,7 +59,7 @@
 							list = $("
")
 							console.log execution
 							for link in execution.links
-								list.append($("").attr('href', link).text(link))
+								list.append($("
").append($("").attr('href', link).text(link)))
 							$("#infolis-modal").append($("
Links:
")).append(list)
 					}


Bug fixes in eventEmitter

Bug fixes in eventEmitter

--- src/eventEmitter.coffee
+++ src/eventEmitter.coffee
@@ -49,7 +49,7 @@
       if refIds.length
         eventData = {
           method: method,
-          collection: collection.rel,
+          collection: camelize(collection.rel),
           refIds: refIds
         }
   return eventData
@@ -86,13 +86,14 @@
     emit(eventData, eventName)

   else if lastUrlPart is 'search'
-    types = data.types
-
-    types.forEach (type) ->
+    collectionName = camelize(urlParts[urlParts.length - 2])
+    type = types.getSingularType(collectionName)
+
+    if type
       eventData = {
         requestId: requestId,
         method: method,
-        collection: urlParts[urlParts.length - 2],
+        collection: collectionName,
         data: data
       }

@@ -101,13 +102,14 @@
       emit(eventData, eventName)

   else
-    type = types.getSingularType(lastUrlPart)
+    collectionName = camelize(lastUrlPart)
+    type = types.getSingularType(collectionName)
     # is this a valid collection?
     if type
       eventData = {
         requestId: requestId,
         method: method,
-        collection: lastUrlPart,
+        collection: collectionName,
         data: data
       }

@@ -133,7 +135,7 @@
     # collection / id from the request URL.
     urlParts = xhr.responseURL.split('/')
     refIds = [parseInt(urlParts[urlParts.length - 1])]
-    collection = urlParts[urlParts.length - 2]
+    collection = camelize(urlParts[urlParts.length - 2])

     type = types.getSingularType(collection)
     # is this a valid collection?
@@ -151,7 +153,8 @@
     data.forEach (response) ->
       # if items exist, return event for each item
       # (this shouldn't really happen very often)
-      type = types.getSingularType(response.collection)
+      collectionName = camelize(response.collection.rel)
+      type = types.getSingularType(collectionName)
       # is this a valid collection?
       if type
         eventData = buildEventDataFromCollection(response.collection, method, refIds)
@@ -191,7 +194,8 @@
             emit(eventData, 'request-response')
   else
     eventData = buildEventDataFromCollection(data.collection, method, refIds)
-    type = types.getSingularType(data.collection)
+    collectionName = camelize(data.collection.rel)
+    type = types.getSingularType(collectionName)
     # is this a valid collection?
     if type and eventData
       eventData.requestId = requestId


Remove beacons after resize

Remove beacons after resize

When game boundary is resized, beacons outside the bounds will be
removed

--- client.coffee
+++ client.coffee
@@ -593,40 +593,41 @@
 				log "beaconMarkers list reset"
 				window.beaconMarkers = [];
 			teamNumber = beacon.get('owner')
-			teamColor=  Db.shared.get('colors', teamNumber, 'hex')
-
-			areaIcon = L.icon({
-				iconUrl: Plugin.resourceUri(teamColor.substring(1) + '.png'),
-				iconSize:     [24, 40],
-				iconAnchor:   [12, 39],
-				popupAnchor:  [-3, -75]
-				shadowUrl: Plugin.resourceUri('markerShadow.png'),
-				shadowSize: [41, 41],
-				shadowAnchor: [12, 39]
-			});
-
-			location = L.latLng(beacon.get('location', 'lat'), beacon.get('location', 'lng'))
-			marker = L.marker(location, {icon: areaIcon})
-			marker.bindPopup("lat: " + location.lat + "
long: " + location.lng)
-			marker.addTo(map)
-			beaconMarkers.push marker
-			#log 'Added marker, marker list: ', beaconMarkers
-
-			# Add the area circle to the map
-			if not window.beaconCircles?
-				log "beaconCircles list reset"
-				window.beaconCircles = [];
-
-
-			circle = L.circle(location, Db.shared.get('game', 'beaconRadius'), {
-				color: teamColor,
-				fillColor: teamColor,
-				fillOpacity: 0.3
-				weight: 2
-			});
-			circle.addTo(map)
-			beaconCircles.push circle
-			log "Added beacon and circle"
+			if teamNumber isnt undefined
+				teamColor=  Db.shared.get('colors', teamNumber, 'hex')
+
+				areaIcon = L.icon({
+					iconUrl: Plugin.resourceUri(teamColor.substring(1) + '.png'),
+					iconSize:     [24, 40],
+					iconAnchor:   [12, 39],
+					popupAnchor:  [-3, -75]
+					shadowUrl: Plugin.resourceUri('markerShadow.png'),
+					shadowSize: [41, 41],
+					shadowAnchor: [12, 39]
+				});
+
+				location = L.latLng(beacon.get('location', 'lat'), beacon.get('location', 'lng'))
+				marker = L.marker(location, {icon: areaIcon})
+				marker.bindPopup("lat: " + location.lat + "
long: " + location.lng)
+				marker.addTo(map)
+				beaconMarkers.push marker
+				#log 'Added marker, marker list: ', beaconMarkers
+
+				# Add the area circle to the map
+				if not window.beaconCircles?
+					log "beaconCircles list reset"
+					window.beaconCircles = [];
+
+
+				circle = L.circle(location, Db.shared.get('game', 'beaconRadius'), {
+					color: teamColor,
+					fillColor: teamColor,
+					fillOpacity: 0.3
+					weight: 2
+				});
+				circle.addTo(map)
+				beaconCircles.push circle
+				log "Added beacon and circle"
 		else
 			log "map not ready yet"
 		Obs.onClean ->
@@ -690,6 +691,7 @@
 	if mapReady()
 		Server.send 'setBounds', window.locationOne.getLatLng(), window.locationTwo.getLatLng(), !->
 			log 'Predict function setbounds?'
+		checkAllBeacons()

 # Compare 2 locations to see if they are the same
 sameLocation = (location1, location2) ->
@@ -699,7 +701,28 @@
 # Check if the map can be used
 mapReady = ->
 	return L? and map?
-
+
+#Loop through all beacons see if they are still within boundaryRectangle
+checkAllBeacons = ->
+	if beaconCircles? and beaconMarkers? and locationOne? and locationTwo? and mapReady()
+		bounds = L.latLngBounds(locationOne.getLatLng(), locationTwo.getLatLng())
+		i = 0;
+		while i<beaconCircles.length
+			if !bounds.contains(beaconCircles[i].getBounds())
+				map.removeLayer beaconCircles[i]
+				invalidMarker =  beaconCircles[i].getLatLng()
+				Server.sync 'deleteMarker', invalidMarker
+				j=0;
+				while j<beaconMarkers.length
+					if sameLocation(beaconMarkers[j].getLatLng(), invalidMarker)
+						map.removeLayer beaconMarkers[j]
+						beaconMarkers.splice(beaconMarkers.indexOf(beaconMarkers[j]), 1)
+					else
+						j++
+				beaconCircles.splice(beaconCircles.indexOf(beaconCircles[i]), 1)
+			else
+				i++
+
 # Render the location of the user on the map (currently broken)
 renderLocation = ->
 	if Geoloc.isSubscribed()


Fix player count bug

Fix player count bug

--- client.coffee
+++ client.coffee
@@ -22,7 +22,7 @@
 		return

 #		Server.call "addUser", userId
-	playercount = Obs.create(Db.shared.get 'settings', 'playercount')
+	playercount = Db.shared.get 'settings', 'playercount'
 	players = JSON.parse(Db.shared.get 'settings', 'players')
 	turn = Db.shared.get 'turn'
 	current = getUser(turn)
@@ -53,10 +53,11 @@
 					margin: '-12px'
 				Ui.bigButton "Draw a card", !->
 					next = +turn + 1
-					if next >= +playercount - 1
-						next = 0
+					if +next >= playercount
+						Server.call 'nextTurn', 0
+					else
+						Server.call 'nextTurn', next

-					Server.call 'nextTurn', next
 					Modal.remove()
 	else
 		if currentcard = Db.shared.get 'currentcard'