Modified plugin to reference itself with this in event handlers

--- src/index.coffee
+++ src/index.coffee
@@ -13,11 +13,11 @@
     if !@options.destination?
       throw new OptionsError 'No destination provided.'

-  buildURL: (message) ->
+  buildURL: (message) =>
     return 'http://api.tropo.com/1.0/sessions?action=create&token=' +
            "#{ @options.token }&msg=#{ message }&number=#{ @options.destination }"

-  receive: (message) ->
+  receive: (message) =>
     parsedURL = url.parse @buildURL message

     client = http.createClient 80, parsedURL.host


* [bug] forget to pass the name argument

--- src/index.coffee
+++ src/index.coffee
@@ -26,7 +26,7 @@
   @param server the express server or server url address
   ###
   constructor: (server, url, name)->
-    return new RequestClient(server, url) unless this instanceof RequestClient
+    return new RequestClient(server, url, name) unless this instanceof RequestClient
     @server = server
     if isFunc url.get
       @app = url


maybe the routing goes via server

maybe the routing goes via server

--- src/index.coffee
+++ src/index.coffee
@@ -46,6 +46,8 @@
 io.of('/teacher')
   .on 'connection', (socket) ->
     socket.emit 'render', onlineData()
+    socket.on 'update', (data) ->
+        socket.emit 'update', data

 io.of('/student')
   .on 'connection', (socket) ->


fix comment

fix comment

--- src/factory/factory.coffee
+++ src/factory/factory.coffee
@@ -35,7 +35,7 @@
     @_group '_isolate'
     @

-  # Create isolated subgraph
+  # Create callback subgraph
   callback: () ->
     @_group '_callback'
     @


Always display outputs from cells

Always display outputs from cells

--- src/core/components/coffeescript.coffee
+++ src/core/components/coffeescript.coffee
@@ -13,7 +13,7 @@

   # XXX special-case functions so that bodies are not printed with the raw renderer.
   render = (input, output) ->
-    sandbox.results[guid] = sandboxResult =
+    sandbox.results[guid] = cellResult =
       result: signal null
       outputs: outputBuffer = Flow.Async.createBuffer []

@@ -52,15 +52,14 @@
       output.error error if error
       output.end()

-      cellResult = sandboxResult.result()
-      if cellResult
-        if isFunction cellResult
-          if isRoutine cellResult
-            print cellResult()
-          else
-            evaluate cellResult
+      result = cellResult.result()
+      if isFunction result
+        if isRoutine result
+          print result()
         else
-          output.close Flow.ObjectBrowser 'result', cellResult
+          evaluate result
+      else
+        output.close Flow.ObjectBrowser 'result', result

   render.isCode = yes
   render


client: wip on initial backbone client for the demo.

--- src/client.coffee
+++ src/client.coffee
@@ -1,40 +1,112 @@
+define 'opendesk.on_demand.client', (exports) ->

-# XXX to organise etc.
+    if not 's'.hasProperty 'startsWith'
+        String::startsWith = (s) -> @indexOf(s) is 0
+        String::endsWith = (s) -> -1 isnt @indexOf s, @length - s.length
+    if not 's'.hasProperty 'contains'
+        String::contains = (s) -> @indexOf(s) > -1

-model:
-    initial_params
-    current_params
+    # We define a single `Model` class with a set of required attributes.
+    class Model extends Backbone.Model
+        defaults:
+            parameters: null
+            initial_choice_doc: null
+            choice_doc: null
+            obj_as_ast: null
+            obj_string: null

-class RenderedView extends Backbone.View
-    render: ->
-        # rebuild the shape objects using @choices model data
-        # pass the shapes to the THREE.Mesh objects
-        # etc.
+        validate: (attrs, options) ->
+            for key of @defaults
+                if not attrs[key]
+                    return "#{ key } is required."

-class Controls extends Backbone.View
-    render: ->
-        # set the `length` etc values from the choice model
+    # Hipster views have mustache templates.
+    class HipsterView extends Backbone.View
+        template: Mustache.to_html

-class Configurator extends Backbone.View
-    initialize: ->
-        @model.bind 'change', @render
-        @params = @model.get 'params'
-        @choice = new Backbone.Model @params.defaults()
+    # The `Controls` view renders a form with inputs for each parameter
+    # and atomically updates the choice doc when the value of any of those
+    # inputs change through user input.
+    class Controls extends HipsterView
+        tmpl: """
+

+

+                {{ #parameters }}
+

+                    {{ @key }}: {{ this }}
+

+                {{ /parameters }}
+

+

+        """

-class Configuration extends Backbone.Model
-    constructor: (@dxf, @params) ->
+        value_types:
+            boolean: 'BOOLEAN'
+            number: 'NUMBER'
+            string: 'STRING'

-class DXF extends Backbone.Model
-    # ... vector data
+        initialize: ->
+            @listenToOnce @model, 'change:parameters', @render

-class ExposedParameters extends Backbone.Model
-    # options sub set
-    defaults: ->
-        # return the default choices
+        render: ->
+            @$el.html @template @tmpl, @model.attributes
+            @$inputs = @$form.find 'input, select'
+            @$inputs.on 'change', @set_choice_doc

-doit = ->
-    el = $('#webgl')
-    params = new ExposedParameters data
-    dxf = new DXF data
-    model = new Configuration dxf, params
-    view = new Configurator model, el
+        get_input_value: (name) ->
+            $input = @$inputs.filter "[attribute='#{ name }']"
+            $input.val()
+
+        get_value_type: (param) ->
+            TYPES = @value_types
+            if _.isObject param and if 'type' of param
+                type_ = param.type_.replace('set::', '')
+                if type_.startsWith 'numeric'
+                    return TYPES.number
+                if type_.contains 'string'
+                    return TYPES.string
+                if type_.contains 'boolean'
+                    return TYPES.boolean
+                throw "Unknown object type: `#{ type_ }`."
+            value = param
+            if _.isArray value
+                value = value[0]
+            type_ = typeof value
+            if type_ of TYPES
+                return TYPES[type_]
+            throw "Unknown value type: `#{ type_ }`."
+
+        set_choice_doc: (args...) ->
+            choice_doc = _.copy @model.get 'choice_doc'
+            for name, parameter of @model.get 'parameters'
+                value = @get_input_value name
+                # XXX dont need to deduce type *here* if we've rendered the
+                # right inputs in the template?
+                # type_ = @get_value_type parameter
+                choice_doc[name] = value
+            @model.set 'choice_doc', choice_doc
+
+    # The `CodeGenerator` contains the core business logic to generate `.obj`
+    # code from the `obj_as_ast` node list and the current parameter values.
+    class CodeGenerator
+        constructor: (@model) ->
+            @listenTo @model, 'change:choice_doc', @generate
+
+        generate: ->
+            obj_as_ast = @model.get 'obj_as_ast'
+            choice_doc = @model.get 'choice_doc'
+
+            # obj_string = ...
+            throw 'NotImplemented: do actual code generation.'
+
+            @model.set 'obj_string', obj_string
+
+    # Entry point -- call `main` with initial model, config and parameter
+    # `data` to setup the client application.
+    main = (data) ->
+          model = new Backbone.Model
+          generator = new CodeGenerator model
+          controls = new ControlsView el: 'controls', model: model
+          model.set data, validate: true
+
+    exports.main = main


Clear the bounty when a brew is completed.

--- src/coffee.coffee
+++ src/coffee.coffee
@@ -281,6 +281,7 @@
       , dibsDuration * 1000

     brewing = {}
+    clearBounty
     robot.brain.save()

   freeSpots = ->


more time for ie?

more time for ie?

--- spec/DeleteGraph.coffee
+++ spec/DeleteGraph.coffee
@@ -44,5 +44,5 @@
         setTimeout ->
           chai.expect( win.location.hash ).to.equal ''
           done()
-        , 1000
-      , 500
+        , 1500
+      , 1500


Fix specs

Fix specs

--- spec/config-spec.coffee
+++ spec/config-spec.coffee
@@ -902,9 +902,9 @@

     describe ".removeScopedSettingsForName(name)", ->
       it "allows properties to be removed by name", ->
-        atom.config.addScopedDefaults("a", ".source.coffee .string.quoted.double.coffee", foo: bar: baz: 42)
-        atom.config.addScopedDefaults("b", ".source .string.quoted.double", foo: bar: baz: 22)
-
-        atom.config.removeScopedSettingsForName("b")
+        disposable1 = atom.config.addScopedDefaults("a", ".source.coffee .string.quoted.double.coffee", foo: bar: baz: 42)
+        disposable2 = atom.config.addScopedDefaults("b", ".source .string.quoted.double", foo: bar: baz: 22)
+
+        disposable2.dispose()
         expect(atom.config.get([".source.js", ".string.quoted.double.js"], "foo.bar.baz")).toBeUndefined()
         expect(atom.config.get([".source.coffee", ".string.quoted.double.coffee"], "foo.bar.baz")).toBe 42


offset now from document not from parent

--- src/cropme.coffee
+++ src/cropme.coffee
@@ -18,6 +18,19 @@
 		if scope.ratio and not scope.height
 			scope.height = scope.destinationHeight
 		scope.type ||= "png"
+
+	offset = (el) ->
+		el = el[0] if el[0]
+		marginTop = window.getComputedStyle(el, null).getPropertyValue("margin-top")
+		marginLeft = window.getComputedStyle(el, null).getPropertyValue("margin-left")
+		offsetTop = -parseInt(marginTop, 10)
+		offsetLeft = -parseInt(marginLeft, 10)
+		while el
+			offsetTop += el.offsetTop
+			offsetLeft += el.offsetLeft
+			el = el.offsetParent
+		top: offsetTop
+		left: offsetLeft

 	template: """
 		<div
@@ -183,8 +196,9 @@
 					checkVRatio()

 		isNearBorders = (coords) ->
-			x = scope.xCropZone + imageAreaEl.offsetLeft
-			y = scope.yCropZone + imageAreaEl.offsetTop
+			offset = offset imageAreaEl
+			x = scope.xCropZone + offset.left
+			y = scope.yCropZone + offset.top
 			w = scope.widthCropZone
 			h = scope.heightCropZone
 			topLeft = { x: x, y: y }
@@ -205,7 +219,7 @@
 			else draggingFn = moveCropZone
 			draggingFn(e)
 		scope.mouseup = (e) ->
-			draggingFn(e)
+			draggingFn(e) if draggingFn
 			draggingFn = null
 		scope.mousemove = (e) ->
 			draggingFn(e) if draggingFn


Add spec for `undefined`

Add spec for `undefined`

--- spec/parser-spec.coffee
+++ spec/parser-spec.coffee
@@ -875,3 +875,17 @@
           Returns undefined.
         """
       }]
+    it "parses return when it contains the keyword `undefined`", ->
+      str = """
+         Public: Get the active {Package} with the given name.
+
+         Returns `undefined`.
+      """
+      doc = parse(str)
+
+      expect(doc.returnValues).toEqualJson [{
+        type: null,
+        description: """
+          Returns `undefined`.
+        """
+      }]


#142 enhance ensureRegister can per-selection register

--- spec/spec-helper.coffee
+++ spec/spec-helper.coffee
@@ -260,7 +260,9 @@

   ensureRegister: (register) ->
     for name, ensure of register
-      reg = @vimState.register.get(name)
+      {selection} = ensure
+      delete ensure.selection
+      reg = @vimState.register.get(name, selection)
       for property, _value of ensure
         expect(reg[property]).toEqual(_value)


Fix deprecation suppression in specs

Fix deprecation suppression in specs

--- spec/spec-helper.coffee
+++ spec/spec-helper.coffee
@@ -207,10 +207,10 @@

 deprecationsSnapshot = null
 jasmine.snapshotDeprecations = ->
-  deprecationsSnapshot = Grim.getDeprecations() # suppress deprecations!!
+  deprecationsSnapshot = _.clone(Grim.deprecations)

 jasmine.restoreDeprecationsSnapshot = ->
-  Grim.grimDeprecations = deprecationsSnapshot
+  Grim.deprecations = deprecationsSnapshot

 addCustomMatchers = (spec) ->
   spec.addMatchers


interpolate all the things

interpolate all the things

--- resources/assets/coffee/react/beatmapset-page/main.coffee
+++ resources/assets/coffee/react/beatmapset-page/main.coffee
@@ -208,6 +208,6 @@
               shortname: diqusShortName
               identifier: "beatmapset_#{@props.beatmapset.id}"
               title: "#{@props.beatmapset.artist} - #{@props.beatmapset.title} (mapped by #{@props.beatmapset.creator})"
-              url: document.location.origin + laroute.route('beatmapsets.show', {beatmapset: @props.beatmapset.id})
+              url: "#{document.location.origin}#{laroute.route('beatmapsets.show', beatmapset: @props.beatmapset.id)}"
               remote_auth_s3: currentUser.disqus_auth?.auth_data
               api_key: currentUser.disqus_auth?.public_key


Fix skeletons.

Fix skeletons.

--- src/brunch.coffee
+++ src/brunch.coffee
@@ -172,7 +172,7 @@
   {rootPath, skeleton} = options

   copySkeleton = (skeletonPath) ->
-    skeletonDir = sysPath.join __dirname, '..', 'skeleton'
+    skeletonDir = sysPath.join __dirname, '..', 'skeletons'
     skeletonPath ?= sysPath.join skeletonDir, 'simple-coffee'
     logger.log 'debug', "Copying skeleton from #{skeletonPath}"

@@ -185,12 +185,8 @@
     mkdirp rootPath, (parseInt 755, 8), (error) ->
       return logger.error error if error?
       sysPath.exists skeletonPath, (exists) ->
-        return copyDirectory skeletonPath if exists
-        brunchSkeletonPath = sysPath.join skeletonDir, skeletonPath
-        sysPath.exists brunchSkeletonPath, (exists) ->
-          unless exists
-            return logger.error "Skeleton '#{skeleton}' doesn't exist"
-          copyDirectory brunchSkeletonPath
+        return logger.error "Skeleton '#{skeleton}' doesn't exist" unless exists
+        copyDirectory skeletonPath

   cloneSkeleton = (URL) ->
     logger.log 'debug', "Cloning skeleton from git URL #{URL}"


made quad names case-insensitive

made quad names case-insensitive

--- src/lexer.coffee
+++ src/lexer.coffee
@@ -44,6 +44,7 @@
       if type in '([{' then stack.push type
       else if type in ')]}' then stack.pop()
       if type isnt 'L' or stack[stack.length - 1] is '{'
+        if value[0] is '⎕' then value = value.toUpperCase()
         tokens.push {type, value, offset, aplCode: s}
     offset += value.length
   tokens.push {type: '$', value: '', offset, aplCode: s}


:arrow_up: atom-shell@0.20

:arrow_up: atom-shell@0.20

--- src/config.coffee
+++ src/config.coffee
@@ -69,7 +69,7 @@
     process.env.ATOM_API_URL ? 'https://atom.io/api'

   getNodeVersion: ->
-    process.env.ATOM_NODE_VERSION ? '0.18.0'
+    process.env.ATOM_NODE_VERSION ? '0.20.0'

   getNodeArch: ->
     switch process.platform


Move GoogleAd out of catalog for now.

Move GoogleAd out of catalog for now.

--- controls/GoogleAd.coffee
+++ controls/GoogleAd.coffee
@@ -1,21 +0,0 @@
-###
-A Google advertisement.
-###
-
-class window.GoogleAd extends Control
-
-  initialize: ->
-    google_ad_client = "ca-pub-6699868724002545"
-    @inDocument ->
-      # Leaderboard
-      google_ad_slot = "7561741805"
-      google_ad_width = 728
-      google_ad_height = 90
-      # Force (re?)load of AdSense script.
-      $.get "http://pagead2.googlesyndication.com/pagead/show_ads.js"
-
-# AdSense globals
-window.google_ad_client = undefined
-window.google_ad_slot = undefined
-window.google_ad_width = undefined
-window.google_ad_height = undefined


moving this hax to my personal ~/.atomicity for now

--- src/editor.coffee
+++ src/editor.coffee
@@ -123,9 +123,3 @@

   bindKey 'fullscreen', 'Command-Shift-Return', (env) ->
     Chrome.toggleFullscreen()
-
-  # HAX
-  # this should go in coffee.coffee or something
-  bindKey 'consolelog', 'Ctrl-L', (env) ->
-    env.editor.insert 'console.log ""'
-    env.editor.navigateLeft()


quick fix #152

quick fix #152

--- lib/status-bar-manager.coffee
+++ lib/status-bar-manager.coffee
@@ -17,7 +17,7 @@
   prefix: 'status-bar-vim-mode-plus'

   constructor: ->
-    (@container = @div(classList: ['inline-block']))
+    (@container = @div(id: "#{@prefix}-container", classList: ['inline-block']))
     .appendChild(@element = @div(id: @prefix))

   initialize: (@statusBar) ->


Updates cursor to normal

Updates cursor to normal

--- co-operator.framer/app.coffee
+++ co-operator.framer/app.coffee
@@ -5,6 +5,8 @@

 canvas = new BackgroundLayer
 	backgroundColor: Utils.randomColor()
+
+document.body.style.cursor = "auto"

 # Grid


remove console log

remove console log

--- app/assets/javascripts/components/kid_mentor_schedules.js.cjsx
+++ app/assets/javascripts/components/kid_mentor_schedules.js.cjsx
@@ -176,8 +176,6 @@
     @triggerChange selectedMentorIds

   triggerChange: (selectedMentorIds) ->
-    console.log @props.selection, selectedMentorIds
-    console.log _.difference @props.selection, selectedMentorIds
     removedIds = _.difference @props.selection, selectedMentorIds
     @props.onChange selectedMentorIds, removedIds


Tweaking filter to be case insensitive

Tweaking filter to be case insensitive

--- app/assets/javascripts/darkswarm/filters/filter_hubs.js.coffee
+++ app/assets/javascripts/darkswarm/filters/filter_hubs.js.coffee
@@ -3,7 +3,7 @@
     hubs ||= []
     text ?= ""
     match = (matched)->
-      matched.indexOf(text) != -1
+      matched.toLowerCase().indexOf(text.toLowerCase()) != -1

     hubs.filter (hub)->
       match(hub.name) or match(hub.address.zipcode) or match(hub.address.city)


Remove unused route

Remove unused route

--- app/assets/javascripts/rglossa/states/corpus/home_route.coffee
+++ app/assets/javascripts/rglossa/states/corpus/home_route.coffee
@@ -1,22 +0,0 @@
-# This route dispatches to the appropriate search interface based on the
-# searchEngine that is set on the corpus (or to a CWB interface if none is
-# specified)
-App.CorpusHomeRoute = Em.Route.extend
-
-  redirect: ->
-    # Choose which search interface to display based on the search type for
-    # the selected corpus. The corpusController determines the search type
-    # from its model (i.e. the corpus), and the corpus is fetched as the model
-    # of the parent route (CorpusRoute). In fact, we don't get here until
-    # Ember has finished loading the parent route model from the server, so we
-    # don't need to set up an observer to wait for it or anything :-)
-    searchEngine = @controllerFor('corpus').get('searchEngine')
-    newRoute = switch searchEngine
-      when 'cwb' then 'cwb.regex'
-
-      # Add routes for other search interfaces/engines here as they are
-      # implemented, e.g.
-      # when 'corpuscle' then 'corpuscleSimple'
-      # when 'annis2' then 'annis2Simple'
-
-    @transitionTo(newRoute)


fix a11y KO navigation for show me links in wizard

fixes CNVS-26676

In the eportfolios wizard, Keyboard only users
should be able to trigger the highlight, whether
it happens when the link is focused or clicked.
Previously it would only highlight on mouseover
events. Now it will highlight on focus events also.

test plan:
1. Navigate to one of the current user's ePortfolios
2. Click on the "Getting Started Wizard" link in the
   body of the Welcome page
3. Move keyboard focus to a "show me" link and note
   that there is now a highlight on the screen

Change-Id: I0d84ac4cb17e8c48f940d4b4bf3163eacea3b82c
Reviewed-on: https://gerrit.instructure.com/81664
Tested-by: Jenkins
QA-Review: Nathan Rogowski <2e8aa918660411855c6d44d5bb2da677aa033255@instructure.com>
Reviewed-by: Matt Berns <e53c8988cd428dde240324ce2797c8eb7073560f@instructure.com>
Product-Review: Pierce Arner <de38b793164d9bfa12fc4185260c174139808169@instructure.com>

--- app/coffeescripts/bundles/legacy/eportfolios_wizard_box.coffee
+++ app/coffeescripts/bundles/legacy/eportfolios_wizard_box.coffee
@@ -3,31 +3,31 @@
   "jquery.instructure_misc_plugins"
 ], ($) ->
   $(document).ready ->
-    $(".sections_list_hover").mouseover ->
+    $(".sections_list_hover").on "mouseover focus", ->
       $("#section_list .section:first").indicate()

-    $(".pages_list_hover").mouseover ->
+    $(".pages_list_hover").on "mouseover focus", ->
       $("#section_pages").indicate()

-    $(".organize_sections_hover").mouseover ->
+    $(".organize_sections_hover").on "mouseover focus", ->
       $(".manage_sections_link").indicate()

-    $(".organize_pages_hover").mouseover ->
+    $(".organize_pages_hover").on "mouseover focus", ->
       $(".manage_pages_link").indicate()

-    $(".eportfolio_settings_hover").mouseover ->
+    $(".eportfolio_settings_hover").on "mouseover focus", ->
       $(".portfolio_settings_link").indicate()

-    $(".edit_content_hover").mouseover ->
+    $(".edit_content_hover").on "mouseover focus", ->
       $(".edit_content_link").indicate()

-    $(".page_settings_hover").mouseover ->
+    $(".page_settings_hover").on "mouseover focus", ->
       $("#edit_page_form .form_content").indicate()

-    $(".page_buttons_hover").mouseover ->
+    $(".page_buttons_hover").on "mouseover focus", ->
       $("#edit_page_sidebar .form_content:last").indicate()

-    $(".page_add_subsection_hover").mouseover ->
+    $(".page_add_subsection_hover").on "mouseover focus", ->
       $("#edit_page_sidebar ul").indicate()

     $("#wizard_box").bind "wizard_opened", ->
@@ -38,5 +38,3 @@

     $(document).bind "editing_page", ->
       $(".wizard_options .option.editing_mode").click()  if $(".wizard_options .option.edit_step").hasClass("selected")
-
-


fix comment.

fix comment.

--- coffee/services/ticket.coffee
+++ coffee/services/ticket.coffee
@@ -25,7 +25,7 @@
   #
   # - in chrome sync,
   #
-  #     ticket = [ id, text, project_url_index, project_id, show ]
+  #     ticket = { id, text, project_url_index, project_id, show }
   #


Only cache underline y position for available fonts

--- coffee/smart-underline.coffee
+++ coffee/smart-underline.coffee
@@ -122,10 +122,34 @@

 backgroundPositionYCache = {}

+getFirstAvailableFont = (fontFamily) ->
+  fonts = fontFamily.split ','
+
+  for font in fonts
+    if fontAvailable font
+      return font
+
+  return false
+
+fontAvailable = (font) ->
+  canvas = document.createElement 'canvas'
+  context = canvas.getContext '2d'
+  text = 'abcdefghijklmnopqrstuvwxyz0123456789'
+  context.font = '72px monospace'
+  baselineSize = context.measureText(text).width
+  context.font = "72px #{ font }, monospace"
+  newSize = context.measureText(text).width
+  return false if newSize is baselineSize
+  return true
+
 getUnderlineBackgroundPositionY = (node) ->
   computedStyle = getComputedStyle node

-  cacheKey = "font:#{ computedStyle.fontFamily }size:#{ computedStyle.fontSize }weight:#{ computedStyle.fontWeight }"
+  firstAvailableFont = getFirstAvailableFont computedStyle.fontFamily
+  if not firstAvailableFont
+    cacheKey = "#{ Math.random() }" # AKA, don’t cache
+  else
+    cacheKey = "font:#{ firstAvailableFont }size:#{ computedStyle.fontSize }weight:#{ computedStyle.fontWeight }"
   cache = backgroundPositionYCache[cacheKey]

   return cache if cache