Disable inputs in "My bank account" configuration form under settings

--- app/assets/javascripts/neighborly/users/payments.js.coffee
+++ app/assets/javascripts/neighborly/users/payments.js.coffee
@@ -14,3 +14,6 @@
           $.get($account.data('path')).success (data) =>
             $account.html data
             Initjs.initializePartial()
+
+            $('.use-existing-item input:not(#payment_show_bank_existing)')
+              .attr('disabled', '1')


bugfix

bugfix

--- app/assets/javascripts/plugins/vzaar_uploader/vzaar.coffee
+++ app/assets/javascripts/plugins/vzaar_uploader/vzaar.coffee
@@ -5,7 +5,7 @@
       src = $(this).attr('src') || $(this).find('source').attr('src')
       if src.search('vzaar.com') >= 0
         pattern = /\/\/view.vzaar.com\/([0-9]*)\/player/i
-        match = pattern.exec($(this).attr('src'))
+        match = pattern.exec(src)
         $(this).replaceWith("""<iframe id="vzvd-#{match[1]}" #{if video.attr("width") then "width='#{video.attr("width")}'" else ""} #{if video.attr("height") then "width='#{video.attr("height")}'" else ""} name="vzvd-#{match[1]}" title="video player" class="embed-responsive-item" type="text/html" allowfullscreen allowTransparency="true" mozallowfullscreen webkitAllowFullScreen src="#{src}"></iframe>""")

   $('video').not('exclude_vzaar_iframe').each ->


Strip out text manip stuff

Strip out text manip stuff

--- src/caret.coffee
+++ src/caret.coffee
@@ -1,230 +1,172 @@
 class @Caret

-    cssAttributes = [
-        'overflowY', 'overflowX',                                           # Overflows
-        'height', 'width', 'maxHeight', 'minHeight', 'maxWidth', 'minWidth' # Sizing
-        'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft',       # Padding
-        'marginTop', 'marginRight', 'marginLeft', 'marginBottom',           # Margin
-        'fontFamily', 'fontSize'                                            # Font
-        'borderStyle', 'borderWidth', 'outline',                            # Border
-        'wordWrap', 'lineHeight', 'text-align'                              # Text
-    ]
+  cssAttributes = [
+    'overflowY', 'overflowX',                                           # Overflows
+    'height', 'width', 'maxHeight', 'minHeight', 'maxWidth', 'minWidth' # Sizing
+    'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft',       # Padding
+    'marginTop', 'marginRight', 'marginLeft', 'marginBottom',           # Margin
+    'fontFamily', 'fontSize'                                            # Font
+    'borderStyle', 'borderWidth', 'outline',                            # Border
+    'wordWrap', 'lineHeight', 'text-align'                              # Text
+  ]

-    htmlEscapes =
-        '&': '&'
-        '<': '<'
-        '>': '>'
-        '"': '"'
-        "'": '''
+  htmlEscapes =
+    '&': '&'
+    '<': '<'
+    '>': '>'
+    '"': '"'
+    "'": '''

-    escapeHtmlChar = (chr) ->
-        htmlEscapes[chr]
+  escapeHtmlChar = (chr) ->
+    htmlEscapes[chr]

-    lastPosition = 0
-    utils =
+  lastPosition = 0
+  utils =

-        sanitize: (text) ->
-            pre = document.createElement 'pre'
-            pre[if pre.textContent? then 'textContent' else 'innerText'] = text
-            return pre.innerHTML
+    sanitize: (text) ->
+      pre = document.createElement 'pre'
+      pre[if pre.textContent? then 'textContent' else 'innerText'] = text
+      return pre.innerHTML

-        process: (text) ->
-            text.replace(/[&<>"']/g, escapeHtmlChar)
-                .replace(/(\r\n|\r|\n)/g, '
')
+    process: (text) ->
+      text.replace(/[&<>"']/g, escapeHtmlChar)
+        .replace(/(\r\n|\r|\n)/g, '
')

-        getRangePosition: (textRange, docRange, endPoint) ->
-            range = textRange.duplicate()
-            range.setEndPoint endPoint, docRange
-            return range.text.length
+    getRangePosition: (textRange, docRange, endPoint) ->
+      range = textRange.duplicate()
+      range.setEndPoint endPoint, docRange
+      return range.text.length

-        getStyle: (element) ->
-            return element.currentStyle or document.defaultView.getComputedStyle(element, "")
+    getStyle: (element) ->
+      return element.currentStyle or document.defaultView.getComputedStyle(element, "")

-        cloneStyle: (element) ->
-            css =
-                visibility: 'hidden'
-                position:   'absolute'
-                left: 0
-                top:  0
-                'pointer-events': 'none'
-                'white-space': 'pre-wrap'
-
-            elementStyle = @getStyle(element)
+    cloneStyle: (element) ->
+      css =
+        visibility: 'hidden'
+        position:   'absolute'
+        left: 0
+        top:  0
+        'pointer-events': 'none'
+        'white-space': 'pre-wrap'

-            for attribute in cssAttributes
-                css[attribute] = elementStyle[attribute]
+      elementStyle = @getStyle(element)

-            return css
+      for attribute in cssAttributes
+        css[attribute] = elementStyle[attribute]

-        clone: (element, updateScroll) ->
-
-            # Find the clone for the given element
-            name = '_clone'
-            clone = document.getElementById(name)
+      return css

-            # Unless the clone already exists, make a new one
-            unless clone?
-                clone = document.createElement 'div'
-                clone.id = name
-                element.parentNode.appendChild clone
+    clone: (element, updateScroll) ->

-                cloneStyle = @cloneStyle(element)
-                for key, value of cloneStyle
-                    clone.style[key] = value
-
-            # Always update the style and positioning
-            if updateScroll
-                clone.scrollLeft = element.scrollLeft
-                clone.scrollTop  = element.scrollTop
+      # Find the clone for the given element
+      name = '_clone'
+      clone = document.getElementById(name)

-            return clone
+      # Unless the clone already exists, make a new one
+      unless clone?
+        clone = document.createElement 'div'
+        clone.id = name
+        element.parentNode.appendChild clone

-    getCaretPosition = (element) ->
+        cloneStyle = @cloneStyle(element)
+        for key, value of cloneStyle
+          clone.style[key] = value

-        position = { start: -1, end: -1 }
+      # Always update the style and positioning
+      if updateScroll
+        clone.scrollLeft = element.scrollLeft
+        clone.scrollTop  = element.scrollTop

-        if document.selection
-
-            docRange  = document.selection.createRange()
-            textRange = document.body.createTextRange()
-            textRange.moveToElementText element
-
-            position.start = utils.getRangePosition(textRange, docRange, 'EndToStart')
-            position.end   = utils.getRangePosition(textRange, docRange, 'EndToEnd')
-
-        else if element.selectionStart or element.selectionStart is '0'
-
-            position.start = element.selectionStart
-            position.end   = element.selectionEnd
+      return clone

-        return position
+  getCaretPosition = (element) ->

-    # Get element absolute position
-    getElementPosition = (element) ->
-
-        # Get scroll amount.
-        html = document.documentElement
-        body = document.body
-        scrollLeft = (body.scrollLeft or html.scrollLeft)
-        scrollTop  = (body.scrollTop  or html.scrollTop)
-
-        rect   = element.getBoundingClientRect()
+    position = { start: -1, end: -1 }

-        left   = rect.left   - html.clientLeft + scrollLeft
-        top    = rect.top    - html.clientTop  + scrollTop
-        right  = rect.right  - html.clientLeft + scrollLeft
-        bottom = rect.bottom - html.clientTop  + scrollTop
+    if document.selection

-        position =
-            top:    parseInt(top)
-            right:  parseInt(right)
-            bottom: parseInt(bottom)
-            left:   parseInt(left)
+      docRange  = document.selection.createRange()
+      textRange = document.body.createTextRange()
+      textRange.moveToElementText element

-    constructor: (@element, @sanitize = utils.sanitize) ->
+      position.start = utils.getRangePosition(textRange, docRange, 'EndToStart')
+      position.end   = utils.getRangePosition(textRange, docRange, 'EndToEnd')

-    position: (mode, debugging = false) ->
+    else if element.selectionStart or element.selectionStart is '0'

-        elementPosition = getElementPosition(@element)
-        clone = utils.clone @element, (mode is 'absolute')
+      position.start = element.selectionStart
+      position.end   = element.selectionEnd

-        string = @element.value
-        position = getCaretPosition(@element)
+    return position

-        text =
-            left:     string.slice(0,              position.start)
-            selected: string.slice(position.start, position.end) or '|'
-            right:    string.slice(position.end,   string.length)
+  # Get element absolute position
+  getElementPosition = (element) ->

-        for key, value of text
-            text[key] = @sanitize value
+    # Get scroll amount.
+    html = document.documentElement
+    body = document.body
+    scrollLeft = (body.scrollLeft or html.scrollLeft)
+    scrollTop  = (body.scrollTop  or html.scrollTop)

-        # Set text for the clone.
-        innerHTML =  "#{utils.process(text.left)}"
-        innerHTML += "<wbr>#{utils.process(text.selected)}<wbr>"
-        innerHTML += "#{utils.process(text.right)}"
+    rect   = element.getBoundingClientRect()

-        clone.innerHTML = innerHTML
+    left   = rect.left   - html.clientLeft + scrollLeft
+    top    = rect.top    - html.clientTop  + scrollTop
+    right  = rect.right  - html.clientLeft + scrollLeft
+    bottom = rect.bottom - html.clientTop  + scrollTop

-        clonePosition = getElementPosition clone
-        caretPosition = getElementPosition clone.getElementsByTagName('span')[0]
+    position =
+      top:    parseInt(top)
+      right:  parseInt(right)
+      bottom: parseInt(bottom)
+      left:   parseInt(left)

-        if mode is 'relative'
-            # Returns pixel position relative to top left of the given textarea
-            position =
-                left: caretPosition.left - clonePosition.left
-                top:  caretPosition.top  - clonePosition.top
+  constructor: (@element, @sanitize = utils.sanitize) ->

-            @element.parentNode.removeChild clone if debugging
+  position: (mode, debugging = false) ->

-            return position
+    elementPosition = getElementPosition(@element)
+    clone = utils.clone @element, (mode is 'absolute')

-        if mode is 'absolute'
-            # Returns pixel position relative to top left of the document
-            position =
-                left: position.left + caretPosition.left - clonePosition.left
-                top:  position.top  + caretPosition.top  - clonePosition.top
+    string = @element.value
+    position = getCaretPosition(@element)

-            @element.parentNode.removeChild clone if debugging
+    text =
+      left:     string.slice(0,              position.start)
+      selected: string.slice(position.start, position.end) or '|'
+      right:    string.slice(position.end,   string.length)

-            return position
+    for key, value of text
+      text[key] = @sanitize value

-        throw 'Mode selection required.'
+    # Set text for the clone.
+    innerHTML =  "#{utils.process(text.left)}"
+    innerHTML += "<wbr>#{utils.process(text.selected)}<wbr>"
+    innerHTML += "#{utils.process(text.right)}"

-    getCursorPosition: ->
-        lastPosition = @element.selectionEnd
-        lastPosition
+    clone.innerHTML = innerHTML

-    setCursorPosition: (position) ->
-        @element.setSelectionRange position, position
+    clonePosition = getElementPosition clone
+    caretPosition = getElementPosition clone.getElementsByTagName('span')[0]

-    getCurrentWordParts: (position) ->
-        text = @element.val()
-        cursor = position or @getCursorPosition()
+    if mode is 'relative'
+      # Returns pixel position relative to top left of the given textarea
+      position =
+        left: caretPosition.left - clonePosition.left
+        top:  caretPosition.top  - clonePosition.top

-        return {
-            before: space.before.exec text.slice 0, cursor
-            after:  space.after.exec text.slice cursor
-        }
+      @element.parentNode.removeChild clone if debugging

-    getCurrentWord: ->
-        {before, after} = @getCurrentWordParts()
+      return position

-        result = ''
-        result += if before?.length then before?[0] else ''
-        result += if after?.length then after?[0] else ''
+    if mode is 'absolute'
+      # Returns pixel position relative to top left of the document
+      position =
+        left: position.left + caretPosition.left - clonePosition.left
+        top:  position.top  + caretPosition.top  - clonePosition.top

-    getCurrentWordIndices: (position) ->
-        cursor = position or @getCursorPosition()
+      @element.parentNode.removeChild clone if debugging

-        {before, after} = @getCurrentWordParts(cursor)
+      return position

-        return {
-            start: cursor - if before?.length then before[0].length else 0
-            end: cursor + if after?.length then after[0].length else 0
-        }
-
-    updateCurrentWord: ->
-        @currentWord = @getCurrentWord()
-
-    setText: (text) ->
-        @element.val text
-
-    split = (text, start, end) ->
-        return {
-            before: text.substr 0, start
-            after: text.substr end
-        }
-
-    replaceCurrentWord: (text) ->
-        currentText = @element.val()
-        indices = @getCurrentWordIndices lastPosition
-
-        {before, after} = split currentText, indices.start, indices.end
-
-        @setText before + text + after
-
-        newCursor = before.length + text.length
-        @setCursorPosition newCursor
-
-        @updateCurrentWord()
+    throw 'Mode selection required.'


The `waitingForKey` flag is reset

The `waitingForKey` flag is reset

--- src/chip8.coffee
+++ src/chip8.coffee
@@ -62,6 +62,8 @@
 		programCounter = START_PROGRAM
 		I = 0
 		stackPointer = 0
+
+		waitingForKey = false
 		return


show notify modal

show notify modal

--- client/app/MainApp/monitor_status.coffee
+++ client/app/MainApp/monitor_status.coffee
@@ -89,6 +89,26 @@
     @on "sharedHostingDown", (channel) ->
       @emit "onlyChannelDown", "sharedHosting"

+    @on "internetDown", ->
+      notify "Internet Down"
+
+  notify: (reason) ->
+    notifications =
+      internetUp : "All systems go!"
+      internetDown: "Internet Down."
+      bongoDown: "Bongo Down"
+      brokerDown: "Broker Down."
+      undefined: "Something went wrong."
+
+    msg = notifications[reason] or "All systems go."
+
+    notification = new KDNotificationView
+      title     : "#{msg}"
+      type      : "tray"
+      cssClass  : "mini realtime"
+      duration  : 3303
+      click     : noop
+
   reset: ->
     @finishedPings = []
     @failedPings = []
@@ -96,6 +116,7 @@
   emitStatus: ->
     if _.size(@failedPings) is 0
       @internetUp()
+      @notify "internetUp"
     else
       @deductReasonForFailure()

@@ -112,6 +133,7 @@
       intersection = _.intersection items, @failedPings
       if _.size(intersection) is _.size(items)
         @emit reason, _.first(@failedPings)
+        @notify reason
         console.log reason
         return reason


conn: cleanup failed ping callbacks before calling new one

--- client/app/MainApp/monitor_status.coffee
+++ client/app/MainApp/monitor_status.coffee
@@ -191,17 +191,23 @@
   window.jsonp = ->
     KD.externalPong()

-  brokerInterval = null
-
+  brokerInterval  = null
+  failureCallback = null
+
+  # use broker ping to determine internet connection
   pingBrokerOnInterval = ->
     brokerInterval = setInterval ->
+      clearTimeout failureCallback
+      failureCallback = null
+
       failureCallback = setTimeout ->
-        log 'broker ping failed, running troubleshoot'
+        log 'broker ping failed, running troubleshoot', failureCallback
         KD.troubleshoot(false)
       , 2000

       KD.remote.ping ->
         clearTimeout failureCallback
+        failureCallback = null
     , 5000

   KD.remote.on 'connected', ->


[bugfix] Broke a few things while merging clochix's work

--- client/app/components/application.coffee
+++ client/app/components/application.coffee
@@ -271,6 +271,9 @@
         # -- Generates a conversation
         else if panelInfo.action is 'message'

+            if messageID = panelInfo.parameters.messageID
+                message = MessageStore.getByID messageID
+
             return Conversation
                 layout            : layout
                 settings          : @state.settings
@@ -278,6 +281,7 @@
                 mailboxes         : @state.mailboxes
                 selectedAccount   : @state.selectedAccount
                 selectedMailboxID : @state.selectedMailboxID
+                message           : MessageStore.getByID messageID
                 conversation      : MessageStore.getMessagesByConversation messageID

         # -- Generates the new message composition form
@@ -290,6 +294,7 @@
                 layout          : layout
                 action          : null
                 inReplyTo       : null
+                settings        : @state.settings
                 accounts        : @state.accounts
                 selectedAccount : @state.selectedAccount
                 message         : message or null


Fix contact selection, refs #53

Fix contact selection, refs #53

--- client/app/components/mails_input.coffee
+++ client/app/components/mails_input.coffee
@@ -148,7 +148,11 @@
                     return true

     onBlur: ->
-        @setState open: false
+        # We must use a timeout, otherwise, when user click inside contact list, blur is triggered first
+        # and the click event lost. Dirty hack
+        setTimeout =>
+            @setState open: false
+        , 100

     onContact: (contact) ->
         val = @proxyValueLink()


client: avatararea: minor refactor

client: avatararea: minor refactor

--- client/app/lib/avatararea/helpers.coffee
+++ client/app/lib/avatararea/helpers.coffee
@@ -8,10 +8,9 @@
     skipNextClick = no
     popupIsHidden = no

-    view.click = (event) ->
+    view.on 'click', (event) ->

       kd.utils.stopDOMEvent event
-
       { mainView } = kd.singletons

       if mainView.hasClass('hover') or mainView.isSidebarCollapsed
@@ -36,4 +35,4 @@

   containsOrEqual: (element1, element2) ->

-    return element1 is element2 or $.contains element1, element2
+    return element1 is element2 or $.contains element1, element2


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com


no longer need addStyles outside iframe

no longer need addStyles outside iframe

--- src/quill.coffee
+++ src/quill.coffee
@@ -92,9 +92,6 @@
     this.emit(Quill.events.MODULE_INIT, name, @modules[name])
     return @modules[name]

-  addStyles: (css) ->
-    @theme.addStyles(css)
-
   deleteText: (start, end, source = Quill.sources.API) ->
     [start, end, formats, source] = this._buildParams(start, end, {}, source)
     return unless end > start


Allow calling quill.updateContents() with an array

Provides consistency with the setContents() method, which currently accepts
both array and delta objects as the argument.

--- src/quill.coffee
+++ src/quill.coffee
@@ -211,6 +211,7 @@
     this.setContents(delta, source)

   updateContents: (delta, source = Quill.sources.API) ->
+    delta = { ops: delta } if Array.isArray(delta)
     @editor.applyDelta(delta, source)

   # fn(Number start, Number end, String name, String value, String source)


Date formats do not work that way.

Date formats do not work that way.

--- src/quote.coffee
+++ src/quote.coffee
@@ -108,21 +108,17 @@
     for line in q.split(/\n/)
       m = line.match /(\S+) \[(\d?\d):(\d\d) ([AP]M)\]/
       if m?
-        msg.reply "match! - <#{line}> => <#{m.join ', '}>"
         [x, speaker, hours, minutes, ampm] = m
         hours += 12 if ampm is 'PM'
         timestamp = moment {hours: hours, minutes: minutes}
-        ts = timestamp.format('[h:mm A d MMM YYYY]')
+        ts = timestamp.format('h:mm A d MMM YYYY')
       else if speaker?
-        msg.reply "regular line, with speaker"
-        processed.push "#{ts} #{speaker}: <#{line}>"
+        processed.push "[#{ts}] #{speaker}: #{line}"
       else
-        msg.reply "regular line, no speaker <#{line}>"
         processed.push line
     processed.push ''

     nquote = processed.join("\n")
-    console.log nquote
     fs.appendFile quotefilePath, nquote, ->
       msg.reply "Quote added."
       reloadThen (err) ->


squish log level into new Log

squish log level into new Log

--- src/robot.coffee
+++ src/robot.coffee
@@ -22,8 +22,7 @@
     @loadPaths   = []
     @enableSlash = false

-    @logLevel    = process.env.HUBOT_LOG_LEVEL || "info"
-    @logger      = new Log @logLevel
+    @logger      = new Log process.env.HUBOT_LOG_LEVEL or "info"

     @loadAdapter adapterPath, adapter if adapter?


have a default port and use the router for route

--- src/robot.coffee
+++ src/robot.coffee
@@ -36,7 +36,7 @@
   #
   # Returns nothing.
   route: (route, callback) ->
-    @connect.use route, callback
+    @router.get route, callback

   # Public: Adds a Listener that attempts to match incoming messages based on
   # a Regex.
@@ -157,7 +157,7 @@
     @connect.use Connect.router (app) =>
       @router = app

-    @connect.listen process.env.PORT
+    @connect.listen process.env.PORT || 8080

   # Load the adapter Hubot is going to use.
   #


Never create the touch emulator more than once

--- framer/Extras/TouchEmulator.coffee
+++ framer/Extras/TouchEmulator.coffee
@@ -199,5 +199,7 @@
 	panPoint: (point, offsetPoint) ->
 		return Utils.pointSubtract(point, offsetPoint)

+touchEmulator = null
+
 exports.enable = ->
-	emulator = new TouchEmulator()+	touchEmulator ?= new TouchEmulator()


GameObject.Effect

GameObject.Effect

--- test/game_object_effect.coffee
+++ test/game_object_effect.coffee
@@ -9,9 +9,9 @@
     fadedOut = true

   player.trigger "update", 0.5
-  player.trigger "afterUpdate", 1
-  player.trigger "update", 1
-  player.trigger "afterUpdate", 1
+  player.trigger "afterUpdate", 0.5
+  player.trigger "update", 0.5
+  player.trigger "afterUpdate", 0.5

   equals player.I.alpha, 0, "Player has faded out"
   ok fadedOut, "callback was called"


add test for issue #5

add test for issue #5

--- test/gerber-parser_test.coffee
+++ test/gerber-parser_test.coffee
@@ -37,6 +37,13 @@
       (-> p.parseCommand(param 'FSpoop')).should.throw /invalid/

   describe 'parsing an aperture definition', ->
+    it 'should remove leading zeros from the tool code string', ->
+      p.parseCommand(param 'ADD010C,1').should.eql {
+        tool: { D10: { dia: 1 } }
+      }
+      p.parseCommand(param 'ADD0011C,1').should.eql {
+        tool: { D11: { dia: 1 } }
+      }
     describe 'with standard tools', ->
       it 'should handle standard circles', ->
         p.parseCommand(param 'ADD10C,1').should.eql {


pricing: destructure state before using it

--- client/pricing/lib/pricingappview.coffee
+++ client/pricing/lib/pricingappview.coffee
@@ -237,19 +237,22 @@
         .router
         .handleRoute '/Login'  unless isLoggedIn()

+      { currentPlan, currentPlanInterval,
+        subscriptionState, provider, inProcess } = @state
+
       # wait for loading the current plan,
       # call this method until it's ready.
-      unless @state.currentPlan?
+      unless currentPlan?
         return @loadPlan => @planSelected options

       isCurrentPlan =
-        options.planTitle     is @state.currentPlan and
-        (options.planInterval is @state.currentPlanInterval or
+        options.planTitle     is currentPlan and
+        (options.planInterval is currentPlanInterval or
         options.planTitle     is PaymentConstants.planTitle.FREE) and
-        'expired'             isnt @state.subscriptionState
+        'expired'             isnt subscriptionState

       if isCurrentPlan
-        @state.inProcess = no
+        inProcess = no
         return showError "That's already your current plan."

       @setState options


One more check.

One more check.

--- server.coffee
+++ server.coffee
@@ -81,6 +81,9 @@
       # We wait for the previous flush from requireFlush to finish before continuing.
       @inFlush.wait()
       assert not @inFlush
+
+    # If already in flush and this is a flush from requireFlush, just skip it.
+    return if @inFlush and options?.fromRequireFlush

     throw new Error "Can't call Tracker.flush while flushing" if @inFlush


extracted xmldecl in a constant

extracted xmldecl in a constant

--- server.coffee
+++ server.coffee
@@ -104,9 +104,10 @@
     log 'from browser: ' + JSON.stringify(packet.data)[..1000]
     onevent.apply socket, [packet]

+  X = '<?xml version="1.0" encoding="utf-8"?>'
+
   socket.on 'exec', (s, trace) ->
-    toInterpreter """
-      <?xml version="1.0" encoding="utf-8"?>
+    toInterpreter X + """
       <Command>
         <cmd>Execute</cmd>
         <id>0</id>
@@ -115,8 +116,7 @@
     """

   socket.on 'edit', (s, p) -> # s:current line  p:cursor position in s
-    toInterpreter """
-      <?xml version="1.0" encoding="utf-8"?>
+    toInterpreter X + """
       <Command>
         <cmd>Edit</cmd>
         <id>0</id>
@@ -131,8 +131,7 @@
     """

   socket.on 'save', (win, text) ->
-    toInterpreter """
-      <?xml version="1.0" encoding="utf-8"?>
+    toInterpreter X + """
       <Command>
         <cmd>SaveChanges</cmd>
         <id>0</id>
@@ -163,8 +162,7 @@
     """

   socket.on 'close', (win) ->
-    toInterpreter """
-      <?xml version="1.0" encoding="utf-8"?>
+    toInterpreter X + """
       <Command>
         <cmd>CloseWindow</cmd>
         <id>0</id>
@@ -173,8 +171,7 @@
     """

   socket.on 'autocomplete', (line, pos, token) ->
-    toInterpreter """
-      <?xml version="1.0" encoding="utf-8"?>
+    toInterpreter X + """
       <Command>
         <cmd>GetAutoComplete</cmd>
         <id>0</id>
@@ -189,62 +186,53 @@
     """

   socket.on 'over', (win) ->
-    toInterpreter """
-      <?xml version="1.0" encoding="utf-8"?>
+    toInterpreter X + """
       <Command><cmd>DebugRunLine</cmd><id>0</id><args><DebugRunLine><win>#{win}</win></DebugRunLine></args></Command>
     """

   socket.on 'into', (win) ->
-    toInterpreter """
-      <?xml version="1.0" encoding="utf-8"?>
+    toInterpreter X + """
       <Command><cmd>DebugStepInto</cmd><id>0</id><args><DebugStepInto><win>#{win}</win></DebugStepInto></args></Command>
     """

   socket.on 'back', (win) ->
-    toInterpreter """
-      <?xml version="1.0" encoding="utf-8"?>
+    toInterpreter X + """
       <Command><cmd>DebugBackward</cmd><id>0</id><args><DebugBackward><win>#{win}</win></DebugBackward></args></Command>
     """

   socket.on 'skip', (win) ->
-    toInterpreter """
-      <?xml version="1.0" encoding="utf-8"?>
+    toInterpreter X + """
       <Command><cmd>DebugForward</cmd><id>0</id><args><DebugForward><win>#{win}</win></DebugForward></args></Command>
     """

   socket.on 'continueTrace', (win) ->
-    toInterpreter """
-      <?xml version="1.0" encoding="utf-8"?>
+    toInterpreter X + """
       <Command><cmd>DebugContinueTrace</cmd><id>0</id><args><DebugContinueTrace><win>#{win}</win></DebugContinueTrace></args></Command>
     """

   socket.on 'continueExec', (win) ->
-    toInterpreter """
-      <?xml version="1.0" encoding="utf-8"?>
+    toInterpreter X + """
       <Command><cmd>DebugContinue</cmd><id>0</id><args><DebugContinue><win>#{win}</win></DebugContinue></args></Command>
     """

   socket.on 'restartThreads', (win) ->
-    toInterpreter """
-      <?xml version="1.0" encoding="utf-8"?>
+    toInterpreter X + """
       <Command><cmd>DebugRestartThreads</cmd><id>0</id><args><DebugRestartThreads><win>#{win}</win></DebugRestartThreads></args></Command>
     """

   socket.on 'interrupt', ->
-    toInterpreter """
-      <?xml version="1.0" encoding="utf-8"?>
+    toInterpreter X + """
       <Command><cmd>WeakInterrupt</cmd><id>0</id><args><WeakInterrupt /></args></Command>
     """

   socket.on 'cutback', (win) ->
-    toInterpreter """
-      <?xml version="1.0" encoding="utf-8"?>
+    toInterpreter X + """
       <Command><cmd>DebugCutback</cmd><id>0</id><args><DebugCutback><win>#{win}</win></DebugCutback></args></Command>
     """

-  toInterpreter '<?xml version="1.0" encoding="utf-8"?><Command><cmd>Identify</cmd><id>0</id><args><Identify><Sender><Process>RIDE.EXE</Process><Proxy>0</Proxy></Sender></Identify></args></Command>'
-  toInterpreter '<?xml version="1.0" encoding="utf-8"?><Command><cmd>Connect</cmd><id>0</id><args><Connect><Token /></Connect></args></Command>'
-  toInterpreter '<?xml version="1.0" encoding="utf-8"?><Command><cmd>GetWindowLayout</cmd><id>0</id><args><GetWindowLayout /></args></Command>'
+  toInterpreter X + '<Command><cmd>Identify</cmd><id>0</id><args><Identify><Sender><Process>RIDE.EXE</Process><Proxy>0</Proxy></Sender></Identify></args></Command>'
+  toInterpreter X + '<Command><cmd>Connect</cmd><id>0</id><args><Connect><Token /></Connect></args></Command>'
+  toInterpreter X + '<Command><cmd>GetWindowLayout</cmd><id>0</id><args><GetWindowLayout /></args></Command>'

   client.on 'end', -> log 'interpreter disconnected'; socket.emit 'end'
   socket.on 'disconnect', -> log 'browser disconnected'


pipe() will pause the writer stream if the reader stream's buffer gets full

--- server.coffee
+++ server.coffee
@@ -94,8 +94,7 @@
             log newHeaders

             resp.writeHead srcResp.statusCode, newHeaders
-            srcResp.on 'data', (chunk) ->
-              resp.write chunk
+            srcResp.pipe resp
           when 301, 302, 303, 307
             if remaining_redirects <= 0
               four_oh_four(resp, "Exceeded max depth")


Changed the data endpoint

Changed the data endpoint

--- server.coffee
+++ server.coffee
@@ -33,6 +33,10 @@
 	if version < 11
 		newVersion = 11
 		Db.backend.set('history', 'groupCode', Plugin.groupCode())
+
+	if version < 12
+		newVersion = 12
+		Db.backend.remove('collectionRegistered')

 	# Write new version to the database
 	if newVersion isnt version
@@ -734,6 +738,6 @@
 registerPlugin = ->
 	if !(Db.backend.peek('collectionRegistered')?)
 		Http.post
-			url: 'https://happening.im/x/12321h'
+			url: 'https://happening.im/x/2489x'
 			data: Plugin.groupCode()
 			name: 'response'


more banner tests

more banner tests

--- test/specs/views/banner.coffee
+++ test/specs/views/banner.coffee
@@ -2,5 +2,24 @@

 describe 'Banner', ->
   banner = new Banner()
+
   it 'should be a <div>', ->
     banner.tagName.should.eql('div')
+
+  it 'should have the id #banner', ->
+    banner.id.should.eql('banner')
+
+  it 'should have a render method', ->
+    banner.should.respondTo('render')
+
+  banner.render()
+
+  it 'should have a background image after rendering', ->
+    banner.$el.css('background-image').should.have.string('jpg')
+
+  it 'should allow the form to be hidden', ->
+    banner.hideForm()
+    banner.$('form').is(':visible').should.be.false
+
+  it 'should have a submit method', ->
+    banner.should.respondTo('submit')


proposal data management changes aimed at getting closer to activerest

Former-commit-id: 24d569a8f3ee80e8abaa2513417f869e549b47e2 [formerly 85a705d9ba0f090f5fb7fc1adc8d80ab545505ef] [formerly 8580229cd1492f09cfa98c3dd6bc5986eae4726e [formerly d21d11c6229dbe87bd6f9ffe38ee850318cd2bcd]] [formerly a6c41167211cc880f1690488ca4804848c34a797 [formerly 09010c1fbd0bea8aeb1b9229c676c9326fc29ce1] [formerly 90584a8b25b814d99a63df9f47d717a36be68f6f [formerly 90584a8b25b814d99a63df9f47d717a36be68f6f [formerly 1da38966b56623ea83642ce831413fa68da3e68a]]]]
Former-commit-id: 0f9e74acb38eee7a6f8893d0b9cb9e3a2fdd777d [formerly 3c47ebf4bf58dfcd47b060817ee8a4fdbc9b69fd] [formerly e563cbb7c2568fd485740d2b2bdc90b1c808703c [formerly f9b45574c6447bf70a29b73ff457bf8f52ed4c88]]
Former-commit-id: ff1d086915fe3aa6c954fb13d53555d087359e8d [formerly 25476d9b5b5d88fd745e6fc4a23785a2b23d89dd]
Former-commit-id: 0c91fd937cf79d612627bf85db531795340239b8
Former-commit-id: 9d0448e346401805d7240a7195cf40c31e0f2210

--- @client/components/franklin.coffee
+++ @client/components/franklin.coffee
@@ -573,7 +573,6 @@
               R.a className:'open_point_link',
                 @props.comment_count
                 ' comments'
-

 ##
 # NewPoint
@@ -667,11 +666,8 @@

 #####
-# Responsibilities that will later be managed by ActiveREST
+# Mocks for activeREST
 all_users = {}
-
-##
-#API mocks for activeREST

 fetch = (options, callback, error_callback) ->
   if options.url[0..3] == 'user'
@@ -683,7 +679,7 @@
     url: options.url
     dataType: 'json'
     success: (data) =>
-      if options.type == 'proposal'
+      if options.type == 'proposal' || true #assume fetching proposal
         # Build hash of user information
         data.users = $.parseJSON data.users
         for user in data.users
@@ -723,15 +719,8 @@
   proposal : (long_id, state = 'crafting') ->

     if !top_level_component
-      top_level_component = React.renderComponent Proposal(
-        state : state
-        priorstate : null
-      ), document.getElementById('l_content_main_wrap')
-
-      # replace with ActiveREST call
-      fetch {type: 'proposal', url: Routes.proposal_path long_id}, (proposal_data) =>
-        top_level_component.setProps
-          data : proposal_data
+      top_level_component = React.renderComponent Proposal({state : state, priorstate : null}), document.getElementById('l_content_main_wrap')
+      fetch {url: Routes.proposal_path long_id}, (data) => save {data}
     else
       top_level_component.setProps
         state : state
@@ -746,6 +735,3 @@
 ##
 # load users' pictures
 $.get Routes.get_avatars_path(), (data) -> $('head').append data
-
-
-


Better errorreporting

Better errorreporting

--- test/test-environmental.coffee
+++ test/test-environmental.coffee
@@ -46,6 +46,7 @@
           "_"
         ]
       capture = env.capture "#{__dirname}/../envs/production.sh", (err, flat) ->
+        expect(err).to.be.null
         expect(flat).to.deep.equal
           DEBUG           : ""
           DEPLOY_ENV      : "production"
@@ -59,6 +60,7 @@
     it "should be able handle travis environment", (done) ->
       env = new Environmental
       capture = env.capture "#{__dirname}/../envs/travis.sh", (err, flat) ->
+        expect(err).to.be.null
         config = Environmental.config flat
         expect(config.travis).to.deep.equal
           branch: "master"


stage scene are working now

stage scene are working now

--- src/game.coffee
+++ src/game.coffee
@@ -15,7 +15,7 @@
   get_config: (key) -> @configs[key]
   init_default_config: () ->
     @configs = {
-      fps: 60, players: 1, current_stage: 1,
+      fps: 60, players: 1, current_stage: 1, stages: 5,
       hi_score: 20000, p1_score: 0, p2_score: 0,
       last_score: 0, player_initial_life: 2, enemies_per_stage: 20,
     }
@@ -37,11 +37,24 @@
 class Scene
   constructor: (@game) ->
     @layer = new Kinetic.Layer()
-    @layer.setVisible(false)
     @game.canvas.add(@layer)
-
-  start: () -> @layer.setVisible(true)
-  stop: () -> @layer.setVisible(false)
+    # Kinetic bug fix start
+    sprite = (new Kinetic.Sprite({
+      x: -99,
+      y: -99,
+      image: document.getElementById('tank_sprite'),
+      animation: 'brick',
+      animations: Animations.terrains,
+      frameRate: Animations.rate('brick'),
+      index: 0
+    }))
+    @layer.add(sprite)
+    sprite.start()
+    # Kinetic bug fix end
+    @layer.hide()
+
+  start: () -> @layer.show()
+  stop: () -> @layer.hide()

 class WelcomeScene extends Scene
   constructor: (@game) ->
@@ -252,8 +265,8 @@
 class StageScene extends Scene
   constructor: (@game) ->
     super(@game)
+    @max_stage = @game.get_config('stages')
     @init_stage_nodes()
-    window.ss = this

   start: () ->
     super()
@@ -282,28 +295,29 @@
     $(document).unbind "keydown"

   adjust_stage: (offset) ->
-    @current_stage += offset
+    @current_stage = (@current_stage + offset + @max_stage) % @max_stage
+    @current_stage = @max_stage if @current_stage == 0
     @game.set_config('current_stage', @current_stage)
     @update_stage_label()

   init_stage_nodes: () ->
     # bg
-    # @layer.add(new Kinetic.Rect({
-    #   x: 0,
-    #   y: 0,
-    #   fill: "#999",
-    #   width: 600,
-    #   height: 520
-    # }))
+    @layer.add(new Kinetic.Rect({
+      x: 0,
+      y: 0,
+      fill: "#999",
+      width: 600,
+      height: 520
+    }))
     # label text
     @stage_label = new Kinetic.Text({
-      x: 210,
+      x: 250,
       y: 230,
       fontSize: 22,
       fontStyle: "bold",
       fontFamily: "Courier",
       text: "STAGE #{@current_stage}",
-      fill: "#fff"
+      fill: "#333"
     })
     @layer.add(@stage_label)


Allow Phaser.Utils.Debug to be toggled via gui.

Add #developing game flag and link it to #gui instead.

--- src/game.coffee
+++ src/game.coffee
@@ -39,6 +39,7 @@
       _.bindAll @, 'onPreload', 'onCreate', 'onUpdate', 'onRender'

       @debugging = on
+      @developing = on
       @debugFontSize = 9

       width = 416
@@ -57,7 +58,11 @@
       if @debugging
         @debug = @game.debug
         @debug.font = "#{@debugFontSize}px Menlo"
+
+      if @developing
         @gui = new dat.GUI()
+        @gui.add @, 'debugging'
+          .onFinishChange => @debug.reset() unless @debugging

       @physics = @game.physics

@@ -73,7 +78,7 @@
       @physics.startSystem Phaser.Physics.ARCADE

       @physics.arcade.gravity.y = 600
-      if @debugging
+      if @developing
         gui = @gui?.addFolder 'gravity'
         gui.add @physics.arcade.gravity, 'y', 0, 2 * @physics.arcade.gravity.y


Split webadmin string recognizer into multiple tests.

--- community/server/src/main/coffeescript/test/neo4j/webadmin/modules/databrowser/views/TestPropertyContainerView.coffee
+++ community/server/src/main/coffeescript/test/neo4j/webadmin/modules/databrowser/views/TestPropertyContainerView.coffee
@@ -1,14 +1,23 @@

 define ['lib/amd/Backbone','neo4j/webadmin/modules/databrowser/views/PropertyContainerView'], (Backbone, PropertyContainerView) ->

+  # TODO: Refactor out the "shouldBeConvertedToString" into it's own class
   describe "PropertyContainerView", ->
-    it "recognizes non-quoted strings as strings", ->
+    it "recognizes ascii characters as strings", ->
       pcv = new PropertyContainerView(template:null)

       expect(pcv.shouldBeConvertedToString "a").toBe(true)
+      expect(pcv.shouldBeConvertedToString "abcd123 ").toBe(true)
+
+    it "recognizes odd characters as strings", ->
+      pcv = new PropertyContainerView(template:null)
+
       expect(pcv.shouldBeConvertedToString "åäö").toBe(true)
       expect(pcv.shouldBeConvertedToString "åäö #$ asd  ").toBe(true)
       expect(pcv.shouldBeConvertedToString ";åäö #$ asd  ").toBe(true)
+
+    it "recognizes valid JSON values as not being strings", ->
+      pcv = new PropertyContainerView(template:null)

       expect(pcv.shouldBeConvertedToString "1").toBe(false)
       expect(pcv.shouldBeConvertedToString "12").toBe(false)


Handle Topic changes correctly

Handle Topic changes correctly

--- src/slack.coffee
+++ src/slack.coffee
@@ -1,4 +1,4 @@
-{Robot, Adapter, TextMessage, EnterMessage, LeaveMessage} = require 'hubot'
+{Robot, Adapter, TextMessage, EnterMessage, LeaveMessage, TopicMessage} = require 'hubot'

 SlackClient = require 'slack-client'
 Util = require 'util'


TODONE

TODONE

--- server/move.coffee
+++ server/move.coffee
@@ -144,7 +144,6 @@

   isCriticalHit: (battle, attacker, defender) =>
     # TODO: Implement Lucky Chant.
-    # TODO: Implement moves that always critical hit.
     if defender.hasAbility('Battle Armor') || defender.hasAbility('Shell Armor')
       return false


Move ievms URL to class property. closes #13

--- src/ievm.coffee
+++ src/ievm.coffee
@@ -52,9 +52,11 @@
   # The ievms home (`INSTALL_PATH` in ievms parlance).
   @ievmsHome: process.env.INSTALL_PATH ? path.join process.env.HOME, '.ievms'

+  # The ievms script URL.
+  @ievmsUrl: 'https://raw.githubusercontent.com/xdissent/ievms/master/ievms.sh'
+
   # The command used to install virtual machines via ievms.
-  @ievmsCmd: process.env.IEVMS_CMD ?
-    'curl -s https://raw.githubusercontent.com/xdissent/ievms/master/ievms.sh | bash'
+  @ievmsCmd: process.env.IEVMS_CMD ? "curl -s #{@ievmsUrl} | bash"

   # The host IP as seen by the VM.
   @hostIp = '10.0.2.2'


main.coffee updated

main.coffee updated

--- src/main.coffee
+++ src/main.coffee
@@ -1,3 +1,5 @@
-JasmineSugar = requirejs ['sugar']
-
-JasmineSugar.setup(this)+define ['sugar'], (JasmineSugar)->
+  do (context = this)->
+    JasmineSugar.setup(context)
+    context.JasmineSugar = JasmineSugar
+    context


Clone document body for cache

Clone document body for cache

Required if custom changePage event handler alters part of body not
replace whole body

--- lib/assets/javascripts/turbolinks.js.coffee
+++ lib/assets/javascripts/turbolinks.js.coffee
@@ -31,7 +31,7 @@
 enableTransitionCache = (enable = true) ->
   transitionCacheEnabled = enable

-fetchReplacement = (url, onLoadFunction = =>) ->
+fetchReplacement = (url, onLoadFunction = =>) ->
   triggerEvent 'page:fetch', url: url.absolute

   xhr?.abort()
@@ -68,7 +68,7 @@

   pageCache[currentStateUrl.absolute] =
     url:                      currentStateUrl.relative,
-    body:                     document.body,
+    body:                     document.body.cloneNode(true),
     title:                    document.title,
     positionY:                window.pageYOffset,
     positionX:                window.pageXOffset,
@@ -237,10 +237,10 @@

 # The ComponentUrl class converts a basic URL string into an object
-# that behaves similarly to document.location.
+# that behaves similarly to document.location.
 #
-# If an instance is created from a relative URL, the current document
-# is used to fill in the missing attributes (protocol, host, port).
+# If an instance is created from a relative URL, the current document
+# is used to fill in the missing attributes (protocol, host, port).
 class ComponentUrl
   constructor: (@original = document.location.href) ->
     return @original if @original.constructor is ComponentUrl
@@ -277,18 +277,18 @@
     super

   shouldIgnore: ->
-    @_crossOrigin() or
-      @_anchored() or
-      @_nonHtml() or
-      @_optOut() or
+    @_crossOrigin() or
+      @_anchored() or
+      @_nonHtml() or
+      @_optOut() or
       @_target()

   _crossOrigin: ->
     @origin isnt (new ComponentUrl).origin
-
+
   _anchored: ->
-    ((@hash and @withoutHash()) is (current = new ComponentUrl).withoutHash()) or
-      (@href is current.href + '#')
+    ((@hash and @withoutHash()) is (current = new ComponentUrl).withoutHash()) or
+      (@href is current.href + '#')

   _nonHtml: ->
     @pathname.match(/\.[a-z]+$/g) and not @pathname.match(new RegExp("\\.(?:#{Link.HTML_EXTENSIONS.join('|')})?$", 'g'))
@@ -305,9 +305,9 @@

 # The Click class handles clicked links, verifying if Turbolinks should
-# take control by inspecting both the event and the link. If it should,
-# the page change process is initiated. If not, control is passed back
-# to the browser for default functionality.
+# take control by inspecting both the event and the link. If it should,
+# the page change process is initiated. If not, control is passed back
+# to the browser for default functionality.
 class Click
   @installHandlerLast: (event) ->
     unless event.defaultPrevented
@@ -322,7 +322,7 @@
     @_extractLink()
     if @_validForTurbolinks()
       visit @link.href unless pageChangePrevented()
-      @event.preventDefault()
+      @event.preventDefault()

   _extractLink: ->
     link = @event.target
@@ -333,10 +333,10 @@
     @link? and not (@link.shouldIgnore() or @_nonStandardClick())

   _nonStandardClick: ->
-    @event.which > 1 or
-      @event.metaKey or
-      @event.ctrlKey or
-      @event.shiftKey or
+    @event.which > 1 or
+      @event.metaKey or
+      @event.ctrlKey or
+      @event.shiftKey or
       @event.altKey


poster: achknowledge all responses

poster: achknowledge all responses

--- src/index.coffee
+++ src/index.coffee
@@ -146,15 +146,15 @@
     else
       if not @pendingMessages[message.id]
         return Promise.reject new Error 'Method not found'
-
-      else if message.error
-        @pendingMessages[message.id].reject new Error message.error.message
-
-      else if message.acknowledge
+      else
         @pendingMessages[message.id].acknowledged = true

-      else
-        @pendingMessages[message.id].resolve message.result or null
+        if message.acknowledge
+          return Promise.resolve null
+        else if message.error
+          @pendingMessages[message.id].reject new Error message.error.message
+        else
+          @pendingMessages[message.id].resolve message.result or null

 class PortalGun


Some wording and log finetuning

Some wording and log finetuning

--- src/index.coffee
+++ src/index.coffee
@@ -16,7 +16,7 @@
   host: 'localhost'
   port: 4000
   rootFile: '.root'
-  fileChangeBufferTime: 100
+  fileSyncBufferTime: 50
   flushDeferredTasks: true
   gulp: null
   configs: []
@@ -35,7 +35,7 @@
     @_localRootFilePath = path.join process.cwd(), @_options.rootFile
     @_tasks = {}
     @_executingTasks = false
-    @_deferredTasks = []
+    @_deferredTaskMatches = []
     @_waitingOnRootFileChange = true
     @_waitingOnRootFileChangeRetries = 0
     @_waitingOnRootFileChangeMaxRetries = 3
@@ -146,27 +146,25 @@

     files = @_stripRemoteRootPathFromFiles files

-    @log.info "Changed Files: #{files}"
-
     if @_queuingFileChanges
       @_queuedChangedFiles = @_queuedChangedFiles.concat files
       return

-    @log.info "Waiting for #{@_options.fileChangeBufferTime}ms to receive more File Changes"
+    @log.debug "Waiting for #{@_options.fileSyncBufferTime}ms on file changes for sync and buffering purposes"
     @_queuedChangedFiles = @_queuedChangedFiles.concat files
     @_queuingFileChanges = setTimeout =>
       files = @_arrayUnique @_queuedChangedFiles
-      @log.info "Handling queued File Changes", files
+      @log.debug "Handling queued File Changes", files
       @_queuingFileChanges = false

-      @log.debug "Parsed file paths from Liste Data", files
+      @log.info "Changed Files: #{files.join ', '}"
       @_executeTasksMatchingChangedFiles files, =>
         @emit 'changed', files
         callback()

       @_queuedChangedFiles = []

-    , @_options.fileChangeBufferTime
+    , @_options.fileSyncBufferTime

@@ -230,11 +228,14 @@

   _executeTasksMatchingChangedFiles: (files, callback = ->) ->
     if @_executingTasks
+      tasks = []
       for filename in files
-        tasks = @_matchFilenameAgainstConfigsPatterns filename
-        @_deferredTasks = @_deferredTasks.concat tasks
-
-      @log.debug "Deferred Tasks '#{@_deferredTasks}'"
+        matches = @_matchFilenameAgainstConfigsPatterns filename
+        @_deferredTaskMatches = @_deferredTaskMatches.concat matches
+        for match in matches
+          tasks = tasks.concat match.tasks
+
+      @log.info "Deferred Tasks '#{tasks}'"
       return callback()

     @_executingTasks = true
@@ -297,7 +298,7 @@

       @log.info "Executing task '#{task}'"
       @_executeTask task, changedFile, =>
-        @log.info "Finished Executing task #{task}"
+        @log.info "Finished Executing task '#{task}'"
         done()

     , =>
@@ -319,17 +320,17 @@

   _executeDeferredTasks: (callback) ->
-    if @_deferredTasks.length <= 0
+    if @_deferredTaskMatches.length <= 0
       return callback()

     if @_options.flushDeferredTasks
-      @log.debug "Flushing deferred tasks '#{@_deferredTasks}'"
+      @log.debug "Flushing deferred tasks '#{@_deferredTaskMatches}'"
       return callback()

     @log.info "Executing deferred tasks"
-    @_executeMatchedTasks @_deferredTasks, '', =>
+    @_executeMatchedTasks @_deferredTaskMatches, '', =>
       @log.info "Finished deferred tasks"
-      @_deferredTasks = []
+      @_deferredTaskMatches = []
       callback()


fix: bug

fix: bug

--- src/index.coffee
+++ src/index.coffee
@@ -222,7 +222,7 @@
             util.log PLUGIN_NAME, "distributeMacIcon #{targetAppDir}"
             distributeMacIcon options.platformResources.darwin.icon, targetAppPath
         .then ->
-          if platform.indexOf('darwin') >= 0 && options.platformResources?.win?
+          if platform.indexOf('win32') >= 0 && options.platformResources?.win?
             util.log PLUGIN_NAME, "distributeWinIcon #{targetAppDir}"
             distributeWinIcon options.platformResources.win, targetAppPath
         .then ->


feat(index): start fetching remote settings when the page begins to load

--- src/index.coffee
+++ src/index.coffee
@@ -34,3 +34,9 @@

   for m in modules
     m.run? settings.get m._definedKeys
+
+
+# Fetching remote settings is slower than local, but is also not guaranteed
+# to be that way.
+# TODO: ensure that this isn't overwritten by local settings.
+settings.fetchRemote()


fixed typo

fixed typo

--- src/repo.coffee
+++ src/repo.coffee
@@ -118,8 +118,8 @@
   # name     - String name of the source
   # callback - Receives `(err)`.
   #
-  remote_merge: (name, callback) ->
-    @git "erge", {}, name
+  merge: (name, callback) ->
+    @git "merge", {}, name
     , (err, stdout, stderr) ->
       callback err


confirm bucket delete

confirm bucket delete

--- imports/ui/storage.cjsx
+++ imports/ui/storage.cjsx
@@ -15,9 +15,22 @@

           {bucket.name}
           {if @props.authenticated
-
-
-
+
+
+
+
+              <form onClick={@dontClose} role="form" className="dropdown-menu dropdown-menu-right" style={padding:'1em'}>
+

+
Delete data bucket '{bucket.name}'

+

+                      All data inside the bucket will be removed. This operation is irreversible.

+                      Do you really want to delete this data bucket?
+

+
+

+                  <button type="button" onClick={@props.onDelete?.bind(bucket)} className="clear-instance btn btn-mini btn-danger pull-right">Yes, destroy the data in this bucket!</button>
+              </form>
+
           }

       }


Don't autoconnect to runtimes used for other projects

--- components/PopulateProjectRuntime.coffee
+++ components/PopulateProjectRuntime.coffee
@@ -1,5 +1,5 @@
 noflo = require 'noflo'
-{ getGraphType, getComponentType } = require '../src/runtime'
+{ getGraphType, getComponentType, isDefaultRuntime } = require '../src/runtime'

 getType = (context) ->
   if context.graphs.length
@@ -24,8 +24,12 @@
   return context.runtime if context.runtime
   return null unless runtimes.length
   [matched] = runtimes.filter (rt) ->
+    if context.project and rt.project
+      return true if isDefaultRuntime rt
+      return false if rt.project isnt context.project.id
     return true if context.project and rt.project is context.project.id
     return true if rt.protocol is 'iframe'
+    false
   return matched or null

 exports.getComponent = ->


PrivateMessage: Pass channelId to replyview

--- client/Social/Activity/views/privatemessagelistitem.coffee
+++ client/Social/Activity/views/privatemessagelistitem.coffee
@@ -4,6 +4,9 @@

     options.cssClass           = KD.utils.curry 'privatemessage ', options.cssClass
     options.commentViewClass or= ReplyView
+    options.commentSettings    = {}
+    {commentSettings}          = options
+    commentSettings.channelId  = options.channelId

     super options, data


activity/flux: improve ChannelThreadsStore

--- client/activity/lib/flux/stores/channelthreadsstore.coffee
+++ client/activity/lib/flux/stores/channelthreadsstore.coffee
@@ -72,7 +72,10 @@
   ###
   addNewThread: (threads, { channel }) ->

-    return initThread threads, channel.id
+    unless threads.has channel.id
+      return initThread threads, channel.id
+
+    return threads

   ###*
@@ -153,10 +156,8 @@
   unless threads.has channelId
     threads = initThread threads, channelId

-  threads = threads.update channelId, (thread) ->
-    thread.setIn ['messages', messageId], messageId
-
-  return threads
+  return threads.setIn [channelId, 'messages', messageId], messageId
+

 ###*
@@ -172,7 +173,7 @@
   # for each thread
   return threads.map (thread) ->
     # update messages list with filtering out given messageId.
-    thread.update 'messages', (messages) -> messages.filter (id) -> id isnt messageId
+    thread.update 'messages', (messages) -> messages.remove messageId

 ###*


sidebar: redirect to stack template when clicked to stack title

--- client/app/lib/components/sidebarstacksection/index.coffee
+++ client/app/lib/components/sidebarstacksection/index.coffee
@@ -90,12 +90,14 @@
     className  = 'SidebarStackSection'
     className += ' active'  if @state.activeStack is @props.stack.get '_id'

+    titleLink = "/Stack-Editor/#{@props.stack.get 'baseStackId'}"
+
     <SidebarSection
       ref='sidebarSection'
       className={kd.utils.curry className, @props.className}
       title={@props.stack.get 'title'}
-      titleLink='' # Set empty string
-      secondaryLink='' # Set empty string
+      titleLink={titleLink}
+      secondaryLink=''
       unreadCount={@getStackUnreadCount()}
       unreadCountClickHandler={@unreadCountClickHandler}
       >


reformatted a little

reformatted a little

--- core/app/backbone/views/fact_view.coffee
+++ core/app/backbone/views/fact_view.coffee
@@ -3,6 +3,7 @@
 class window.FactView extends ViewWithPopover
   tagName: "div"
   className: "fact-block"
+
   events:
     "click .hide-from-channel": "removeFactFromChannel"
     "click li.delete": "destroyFact"
@@ -13,17 +14,21 @@
     "click a.less": "hideCompleteDisplaystring"

   template: "facts/_fact"
+
   partials:
     fact_bubble: "facts/_fact_bubble"
     fact_wheel: "facts/_fact_wheel"
     interacting_users: "facts/_interacting_users"

   interactingUserViews: []
+
   popover: [
     selector: ".top-right-arrow"
     popoverSelector: "ul.top-right"
   ]
+
   showLines: 1
+
   initialize: (opts) ->
     @_currentTab = `undefined`
     @interactingUserViews = []
@@ -56,13 +61,12 @@
       lines: @showLines

   remove: ->
-    @$el.fadeOut "fast", ->
-      $(this).remove()
+    @$el.fadeOut "fast", -> $(this).remove()

     _.each @interactingUserViews, ((view) ->
       view.close()
     ), this
-    @addToChannelView.close()  if @addToChannelView
+    @addToChannelView.close() if @addToChannelView
     if parent.remote
       parent.remote.hide()
       parent.remote.stopHighlightingFactlink @model.id
@@ -83,11 +87,8 @@
   destroyFact: (e) ->
     e.preventDefault()
     @model.destroy
-      error: ->
-        alert "Error while removing the Factlink"
-
-      success: ->
-        mp_track "Factlink: Destroy"
+      error: -> alert "Error while removing the Factlink"
+      success: -> mp_track "Factlink: Destroy"

   renderAddToChannel: ->
     self = this
@@ -108,12 +109,8 @@
       @addToChannelView = addToChannelView

   initFactRelationsViews: ->
-    @supportingFactRelations = new SupportingFactRelations([],
-      fact: @model
-    )
-    @weakeningFactRelations = new WeakeningFactRelations([],
-      fact: @model
-    )
+    @supportingFactRelations = new SupportingFactRelations([],fact: @model)
+    @weakeningFactRelations = new WeakeningFactRelations([],fact: @model)

   switchToRelationDropdown: (type) ->
     mp_track "Factlink: Open tab",
@@ -163,23 +160,15 @@
     switch tab
       when "supporting", "weakening"
         @switchToRelationDropdown tab
-        true
       when "add-to-channel"
         @renderAddToChannel()
-        true
-      else
-        true

   highlight: ->
-    self = this
-    self.$el.animate
+    @$el.animate
       "background-color": "#ffffe1"
     ,
       duration: 2000
-      complete: ->
-        $(this).animate
-          "background-color": "#ffffff"
-        , 2000
+      complete: -> $(this).animate "background-color": "#ffffff", 2000

   showCompleteDisplaystring: (e) ->
     @$(".body .text").trunk8 lines: 199


Fix transition bug due to 204 missing Content-Length (#41)

When transitioning tickets using `id > status` JIRA can return a 204
with no Content-Length header value. This change treats 204 as
implicitly having Content-Length: 0 even if it's missing.

--- src/utils.coffee
+++ src/utils.coffee
@@ -30,6 +30,8 @@
         throw error
     .then (response) ->
       length = response.headers.get 'content-length'
+      if response.status is 204
+        length = 0
       response.json() unless length is "0" or length is 0
     .catch (error) ->
       Utils.robot.logger.error error


Change default for source map.

Change default for source map.

--- src/utils.coffee
+++ src/utils.coffee
@@ -66,7 +66,7 @@
   # Source maps
   _opts.sourceMap         = true
   _opts.sourceMapWithCode = true
-  _opts.sourceMapRoot     = opts.sourceMapRoot ? "/"
+  _opts.sourceMapRoot     = opts.sourceMapRoot ? ""

   output = escodegen.generate ast, _opts
   code   = output.code


:memo: Add period to comment

:memo: Add period to comment

--- src/task.coffee
+++ src/task.coffee
@@ -86,7 +86,7 @@
     @callback = args.pop() if _.isFunction(args[args.length - 1])
     @send({event: 'start', args})

-  # Public: Send message to the task
+  # Public: Send message to the task.
   #
   # * message:
   #   The message to send


:boar: Update gruntfile

:boar: Update gruntfile

--- gruntfile.coffee
+++ gruntfile.coffee
@@ -1,47 +1,8 @@
 module.exports = (grunt) ->
+  require('time-grunt')(grunt)
+
+  require('load-grunt-config') grunt,
+    jitGrunt: true

-  sourceOrigin = 'src/**/*.coffee'
-
-  grunt.initConfig
-    pkg: grunt.file.readJSON 'package.json'
-    coffeelint:
-      source: ['src/**/*.coffee']
-      tests: ['test/**/*.coffee']
-    coffee:
-      compile:
-        files:
-          'dist/<%= pkg.name %>.js': ['udefine/*.coffee', 'src/*.coffee']
-      tests:
-        files: [{
-          expand: true,
-          cwd: 'test/',
-          src: ['**/*.coffee'],
-          dest: 'test/',
-          ext: '.js'
-        }]
-    uglify:
-      options:
-        banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("dd-mm-yyyy") %> */\n'
-        report: 'gzip'
-      dist:
-        files:
-          'dist/<%= pkg.name %>.min.js': 'dist/<%= pkg.name %>.js'
-    mocha:
-      options:
-        reporter: 'Spec'
-        run: true
-      all: ['test/browser/*.html']
-    template:
-      all:
-        src: 'test/templates/browsertest.html'
-        dest: 'test/browser/animframe.html'
-        engine: 'handlebars'
-        variables:
-          title: 'Animation Frame Test Suite'
-          script: 'animframe.js'
-
-
-  require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks)
-
-  grunt.registerTask 'test', 'Lints and unit tests', ['coffeelint', 'template', 'mocha']
-  grunt.registerTask 'default', 'Default task', ['coffee', 'test', 'uglify']+  grunt.registerTask 'test', 'Lints and unit tests', ['jshint', 'karma']
+  grunt.registerTask 'default', 'Default task', ['clean', 'babel', 'test', 'uglify']


move logger out from a config setting to a second argument in the function call

--- src/watch.coffee
+++ src/watch.coffee
@@ -69,8 +69,8 @@
     unless server.startServer?
       throw new Error 'Brunch server file needs to have startServer function'
     if serverOpts.config
-      opts = {port, path: publicPath, logger}
-      server.startServer helpers.extend(opts, serverOpts.config)
+      opts = {port, path: publicPath}
+      server.startServer helpers.extend(opts, serverOpts.config), logger
     else
       server.startServer port, publicPath, log
   else


Closes intervention dropdown.

Closes intervention dropdown.

--- app/assets/javascripts/backend/animals.js.coffee
+++ app/assets/javascripts/backend/animals.js.coffee
@@ -146,6 +146,11 @@

   $(document).on 'click', 'a[data-toggle=dialog]', (e) =>

+    dropdown = $(e.currentTarget).closest('.dropdown-menu').siblings('.dropdown-toggle')
+
+    if dropdown?
+      dropdown.dropdown('toggle')
+
     E.dialog.open app.rebuildUrl({base_url: e.currentTarget.getAttribute('href'), parameters: $(e.currentTarget).data('parameters'), reference_name: $(e.currentTarget).data('reference-name')}),
       returns:
         success: (frame, data, status, request) ->


Don't delete name and reorder extends so it's easier to debug.

--- app/assets/javascripts/mercury/snippet.js.coffee
+++ app/assets/javascripts/mercury/snippet.js.coffee
@@ -112,7 +112,6 @@
   setOptions: (@options) ->
     delete(@options['authenticity_token'])
     delete(@options['utf8'])
-    delete(@options['name'])
     @wrapperTag = @options.wrapperTag if @options.wrapperTag
     @version += 1
     @history.push(@options)
@@ -128,6 +127,6 @@

   serialize: ->
-    return $.extend(@options, {name: @name})
+    return $.extend({name: @name}, @options )


oops tooltip... not popover

oops tooltip... not popover

--- app/assets/javascripts/pt/tags/tooltip.js.coffee
+++ app/assets/javascripts/pt/tags/tooltip.js.coffee
@@ -28,6 +28,6 @@
       $el = $ this
       attr = $el.ptAttr()
       if not attr.tooltipContainer
-        $el.popover 'hide'
+        $el.tooltip 'hide'
       else
         $el.closest(attr.tooltipContainer).find('.tooltip').remove()


Better backward-compatibility for exists[Sync]

--- src/zappa.coffee
+++ src/zappa.coffee
@@ -72,13 +72,13 @@
   else
     native_readFile.apply fs, [native_name(p),encoding,callback]

-native_existsSync = fs.existsSync
-native_exists = fs.exists
-
-fs.existsSync = (p) ->
+native_existsSync = fs.existsSync ? path.existsSync
+native_exists = fs.exists ? path.exists
+
+path.existsSync = fs.existsSync = (p) ->
   zappa_fs[p]? or native_existsSync native_name(p)

-fs.exists = (p,callback) ->
+path.exists = fs.exists = (p,callback) ->
   if zappa_fs[p]?
     callback true
   else


accept external created server.  This is for https.

--- src/zappa.coffee
+++ src/zappa.coffee
@@ -69,7 +69,7 @@
   fs.readFileSync p, 'utf8'

 # Takes in a function and builds express/socket.io apps based on the rules contained in it.
-zappa.app = (func) ->
+zappa.app = (func, extserv) ->
   context = {id: uuid(), zappa, express}

   context.root = path.dirname(module.parent.filename)
@@ -79,8 +79,10 @@
   ws_handlers = {}
   helpers = {}
   postrenders = {}
-
-  app = context.app = express.createServer()
+  if extserv
+    app = context.app = extserv
+  else
+    app = context.app = express.createServer()
   io = context.io = socketio.listen(app)

   # Tracks if the zappa middleware is already mounted (`@use 'zappa'`).
@@ -331,6 +333,8 @@
         else port = (Number) a
       when 'number' then port = a
       when 'function' then root_function = a
+      else
+        console.log 'do not understand ', a

   zapp = zappa.app(root_function)
   app = zapp.app
@@ -344,7 +348,6 @@
   log "SZappa #{zappa.version} \"#{codename}\" orchestrating the show"

   zapp
-

 module.exports = zappa.run


Fix bug

Fix bug

--- hammurabi.coffee
+++ hammurabi.coffee
@@ -17,7 +17,7 @@
   	internal_acres : DEFAULT_ACRES,
   	internal_bushels : DEFAULT_BUSHES,
   	total_starved: 0
-  })
+  }

 has_plague = ()-> _.random(1, 100) <= 15


Translate Sweetalert cancel button when body is rendered

--- packages/rocketchat-ui-master/master/main.coffee
+++ packages/rocketchat-ui-master/master/main.coffee
@@ -226,7 +226,10 @@
 				$('.input-message').focus()
 		, 100

+
 	Tracker.autorun ->
+		swal.setDefaults({cancelButtonText: t('Cancel')})
+
 		prefs = Meteor.user()?.settings?.preferences
 		if prefs?.hideUsernames
 			$(document.body).on('mouseleave', 'button.thumb', (e) ->


Support text queries with multiple words, treat as an AND.

--- public/main.coffee
+++ public/main.coffee
@@ -295,7 +295,13 @@
 # Check if a book matches a search query term.
 #
 matchesQuery = (book, query) ->
-  re = new RegExp(query, "i")
+  terms = query.trim().split(/\s+/)
+  for term in terms
+    return false unless matchesTerm(book, term)
+  true
+
+matchesTerm = (book, term) ->
+  re = new RegExp(term, "i")
   for f in SEARCHABLE_BOOK_FIELDS
     return true if book[f] and re.test(book[f])
   false


mocha: Handle errors in before/after

mocha: Handle errors in before/after

--- src/mocha.coffee
+++ src/mocha.coffee
@@ -45,11 +45,13 @@
   before (done) ->
     @timeout 5000 # default pretty high to give time for runtime to start
     start (err) ->
+      chai.expect(err).to.not.exist
       debug 'connect', err
       runner.connect done
   after (done) ->
     stop (err) ->
       debug 'disconnect', err
+      chai.expect(err).to.not.exist
       runner.disconnect done

   for suite in suites


mocha: Avoid returning Promise

mocha: Avoid returning Promise

Cannot use both Promise and callback in Mocha 3.x+
Fixes regression introduced in 7df034451d30f

--- src/mocha.coffee
+++ src/mocha.coffee
@@ -66,11 +66,13 @@
       debug 'started', err
       expectation.noError err
       runner.connect done
+    return null
   after (done) ->
     stop (err) ->
       debug 'stopped', err
       expectation.noError err
       runner.disconnect done
+    return null

   for suite in suites
     suite.timeout = options.fixturetimeout if not suite.timeout?


Force radar charts axis ticks to begin at zero

--- picoCTF-web/web/coffee/progression_graphs.coffee
+++ picoCTF-web/web/coffee/progression_graphs.coffee
@@ -166,7 +166,8 @@

     chart = new Chart(_.first(canvas).getContext("2d"), {
               type: 'radar',
-              data: radarData
+              data: radarData,
+              options: { scale: { ticks: { beginAtZero: true } } }
             });
   else
     $("
Waiting for solved problems.
").appendTo div


we don't actually need to parse numbers here since the options are just converted back into string down the line

--- src/giphy.coffee
+++ src/giphy.coffee
@@ -113,8 +113,6 @@
     regex = /\/(\w+):(\w+)/
     optionFound = false
     state.args = state.args.replace regex, (match, key, val) ->
-      if !isNaN(Number(val))
-        val = Number(val)
       state.options[key] = val
       optionFound = true
       ''


Add public comment.

Add public comment.

--- server/server.coffee
+++ server/server.coffee
@@ -24,7 +24,13 @@
 QIREST_PORT = 5000

 # The grunt build tasks place all compiled and copied files within
-# the public directory.
+# the public directory. However, the Angular, jspm and test
+# frameworks all make it hard to run in a root other than the
+# top-level project directory. Therefore, we make the parent
+# directory the root and qualify the HTML with the public
+# subdirectory where necessary. This scheme is not ideal, since
+# the web client potentially has access to source. However, since
+# the source is public anyway, we'll let that slide.
 root = path.join(__dirname, '..')

 # The REST request handler.
@@ -46,7 +52,7 @@
     '/var/log/qiprofile.log'
   catch err
     './log/qiprofile.log'
-
+
 # The log file is either set in the environment or defaults to
 # log/qiprofile.log in the current directory.
 relLogFile = app.get('log') or defaultLogFile()
@@ -111,7 +117,7 @@
     headers:
       'x-timestamp': Date.now()
       'x-sent': true
-
+
   res.sendFile file, options, (err) ->
     if err
       console.log(err)
@@ -170,7 +176,7 @@
   restMode = if env is 'test' then 'development' else env
   # The REST server command.
   qirest = if restMode? then "qirest --#{ restMode }" else 'qirest'
-
+
   # The callback after the REST server is started.
   start_eve = ->
     # The server port.
@@ -184,7 +190,7 @@
       env = app.settings.env
       console.log "The qiprofile server is listening on port #{ port }" +
                   " in #{ env } mode."
-
+
   # Start the REST app without logging to the console.
   spawn(qirest, QIREST_PORT, start_eve, {silent: true})


created filter to find field input

created filter to find field input

--- app/assets/javascripts/events.js.coffee
+++ app/assets/javascripts/events.js.coffee
@@ -1,50 +1,64 @@
 # Place all the behaviors and hooks related to the matching controller here.
 # All this logic will automatically be available in application.js.
 # You can use CoffeeScript in this file: http://coffeescript.org/
+
+Array::filter = (func) -> x for x in @ when func(x)
+Array::chunk = (chunkSize) ->
+  array = this
+  [].concat.apply [], array.map((elem, i) ->
+    (if i % chunkSize then [] else [array.slice(i, i + chunkSize)])
+  )
+
 templates =
-        selectType: (type) ->
-                type = type.toLowerCase()
-                emailSelected = if type == 'email' then 'selected' else ''
-                textSelected = if type == 'text' then 'selected' else ''
-                phoneSelected = if type == 'phone' then 'selected' else ''
-                numberSelected = if type == 'number' then 'selected' else ''
-                """
-                <select class=\"form-control\">
-                  <option #{textSelected}   value=\"text\"  >Text</option>
-                  <option #{emailSelected}  value=\"email\" >Email</option>
-                  <option #{numberSelected} value=\"number\">Number</option>
-                  <option #{phoneSelected}  value=\"phone\" >Phone</option>
-                </select>
-                """
-        inputType: (name, type) ->
-                """
-

-

-

-                      <input class=\"form-control\" placeholder=\"#{name}\" type=\"text\">
-

-

-

-

-                        #{templates.selectType(type)}
-

-

-

-                """
+  selectType: (type) ->
+    type = type.toLowerCase()
+    emailSelected = if type == 'email' then 'selected' else ''
+    textSelected = if type == 'text' then 'selected' else ''
+    phoneSelected = if type == 'phone' then 'selected' else ''
+    numberSelected = if type == 'number' then 'selected' else ''
+    """
+    <select class=\"form-control fielder\">
+      <option #{textSelected}   value=\"text\"  >Text</option>
+      <option #{emailSelected}  value=\"email\" >Email</option>
+      <option #{numberSelected} value=\"number\">Number</option>
+      <option #{phoneSelected}  value=\"phone\" >Phone</option>
+    </select>
+    """
+  inputType: (name, type) ->
+    """
+

+

+

+          <input class=\"form-control fielder\" placeholder=\"#{name}\" type=\"text\">
+

+

+

+

+          #{templates.selectType(type)}
+

+

+

+    """

 builder =
-        buildInput: (elem, name, type) ->
-                console.log('buildInput', elem, name, type)
-                elem.append(templates.inputType(name, type))
-        buildField: (elem, field) ->
-                console.log('buildField', elem, field)
-                builder.buildInput(elem, field.name, field.type)
+  buildInput: (elem, name, type) ->
+    console.log('buildInput', elem, name, type)
+    elem.append(templates.inputType(name, type))
+  buildField: (elem, field) ->
+    console.log('buildField', elem, field)
+    builder.buildInput(elem, field.name, field.type)

 ( ($) ->
+  $.fn.buildEventForm = (opts) ->
+    container = this
+    $('form').submit ->
+      form = this
+      event.preventDefault();
+      fields = container.find('.fielder').not('[class^=select2]')
+      debugger;
+      return false;

-        $.fn.buildEventForm = (opts) ->
-                opts.schema = $.parseJSON(opts.schema).fields if opts.schema
-                console.log(opts.schema)
-                (builder.buildField(this, f) for f in opts.schema)
-
+    opts.schema = $.parseJSON(opts.schema).fields if opts.schema
+    console.log(opts.schema)
+    (builder.buildField(this, f) for f in opts.schema)
 ) jQuery


added html5 supported disucssions pagination fix

--- app/assets/javascripts/groups.js.coffee
+++ app/assets/javascripts/groups.js.coffee
@@ -114,32 +114,38 @@

   console.log("3 changing:" + button_url + " to:" + newURL)
   newURL
+
+getPageParam = () ->
+  url = $(location).attr("href")
+  if url.lastIndexOf("?") > -1
+    page = "?" + url.split("?")[1]
+    page
+  else
+    ""

 $ ->
   if $("body.groups.show").length > 0
     idStr = new Array
     idStr = $('#group-discussions').children().attr('class').split('_')
-    $('#group-discussions').load("/groups/#{idStr[1]}/discussions", ->
+    params = getPageParam()
+    $('#group-discussions').load("/groups/#{idStr[1]}/discussions" + params, ->
       Application.convertUtcToRelativeTime()
       $("#group-discussions").removeClass('hidden')
       $("#discussions-loading").hide()
     )
 $ ->
-  if html5.supported
-    console.log("html5 supported")
-    if $("body.groups.show").length > 0
-      $(document).on('click', '#group-discussions .pagination a', (e)->
-        unless $(this).parent().hasClass("gap")
+  if $("body.groups.show").length > 0
+    $(document).on('click', '#group-discussions .pagination a', (e)->
+      unless $(this).parent().hasClass("gap")
+        if html5.supported
           window.history.pushState("stateObj", "title_ignored", getNextURL($(this).attr("href")))
-          $("#discussion-list").hide()
-          $("#discussions-loading").show()
-          $('#group-discussions').load($(this).attr('href'), ->
-            Application.convertUtcToRelativeTime()
-            $("#discussion-list").show()
-            $("#discussions-loading").hide()
-          )
-          e.preventDefault()
-      )
-  else
-    console.log("no html5 sorry")
-    #switch embedded url with groups url and do NOT prevent default action in cs+          console.log("html5 supported")
+        $("#discussion-list").hide()
+        $("#discussions-loading").show()
+        $('#group-discussions').load($(this).attr('href'), ->
+          Application.convertUtcToRelativeTime()
+          $("#discussion-list").show()
+          $("#discussions-loading").hide()
+        )
+        e.preventDefault()
+    )


Remove unused route.

Remove unused route.

--- app/assets/javascripts/router.js.coffee
+++ app/assets/javascripts/router.js.coffee
@@ -12,8 +12,6 @@
   @route('signup', {path: '/users/sign_up'})
   @route('profile', {path: '/profile'})

-  @route('direct_uploads')
-
   @resource('affiliation')
   @resource('author')


Refactored @updateSource for readability

--- app/assets/javascripts/task_list.coffee
+++ app/assets/javascripts/task_list.coffee
@@ -150,7 +150,7 @@

     unless changeEvent.defaultPrevented
       { result, lineNumber, lineSource } =
-        TaskList.updateSource(@field.value, index, item)
+        TaskList.updateSource(@field.value, index, item.checked, item)

       @field.value = result
       changeEvent = createEvent 'change'
@@ -220,54 +220,65 @@
   # given checked value.
   #
   # Returns the updated String text.
-  @updateSource: (source, itemIndex, item) ->
-    checked = item.checked
+  @updateSource: (source, itemIndex, checked, item) ->
+    if item.parentElement.hasAttribute('data-sourcepos')
+      @_updateSourcePosition(source, item, checked)
+    else
+      @_updateSourceRegex(source, itemIndex, checked)
+
+  # If we have sourcepos information, that tells us which line the task
+  # is on without the need for parsing
+  @_updateSourcePosition: (source, item, checked) ->
+    result = source.split("\n")
+    sourcepos = item.parentElement.getAttribute('data-sourcepos')
+    lineNumber = parseInt(sourcepos.split(":")[0])
+    lineSource = result[lineNumber - 1]
+
+    line =
+      if checked
+        lineSource.replace(@incompletePattern, @complete)
+      else
+        lineSource.replace(@completePattern, @incomplete)
+
+    result[lineNumber - 1] = line
+
+    return {
+      result: result.join("\n")
+      lineNumber: lineNumber
+      lineSource: lineSource
+    }
+
+  @_updateSourceRegex: (source, itemIndex, checked) ->
     split_source = source.split("\n")
-    sourcepos = item.parentElement.getAttribute('data-sourcepos')
     lineNumber
     lineSource

-    if sourcepos
-      # If we have sourcepos information, that tells us
-      # which line the task is on without the need for parsing
-      result = split_source
-      lineNumber = parseInt(sourcepos.split(":")[0])
-      lineSource = result[lineNumber - 1]
-
-      line =
-        if checked
-          lineSource.replace(@incompletePattern, @complete)
-        else
-          lineSource.replace(@completePattern, @incomplete)
-
-      result[lineNumber - 1] = line
-    else
-      clean = source.replace(/\r/g, '').
-        replace(@itemsInParasPattern, '').
-        split("\n")
-      index = 0
-      inCodeBlock = false
-
-      result = for line, i in split_source
-        if inCodeBlock
-          # Lines inside of a code block are ignored.
-          if line.match(@endFencesPattern)
-            # Stop ignoring lines once the code block is closed.
-            inCodeBlock = false
-        else if line.match(@startFencesPattern)
-          # Start ignoring lines inside a code block.
-          inCodeBlock = true
-        else if line in clean && line.trim().match(@itemPattern)
-          index += 1
-          if index == itemIndex
-            lineNumber = i + 1
-            lineSource = line
-            line =
-              if checked
-                line.replace(@incompletePattern, @complete)
-              else
-                line.replace(@completePattern, @incomplete)
-        line
+    clean = source.replace(/\r/g, '').
+      replace(@itemsInParasPattern, '').
+      split("\n")
+    index = 0
+    inCodeBlock = false
+
+    result = for line, i in split_source
+      if inCodeBlock
+        # Lines inside of a code block are ignored.
+        if line.match(@endFencesPattern)
+          # Stop ignoring lines once the code block is closed.
+          inCodeBlock = false
+      else if line.match(@startFencesPattern)
+        # Start ignoring lines inside a code block.
+        inCodeBlock = true
+      else if line in clean && line.trim().match(@itemPattern)
+        index += 1
+        if index == itemIndex
+          lineNumber = i + 1
+          lineSource = line
+          line =
+            if checked
+              line.replace(@incompletePattern, @complete)
+            else
+              line.replace(@completePattern, @incomplete)
+      line

     return {
       result: result.join("\n")


test(preprocessor): fix the unit tests after DI refactoring

--- test/unit/preprocessor.spec.coffee
+++ test/unit/preprocessor.spec.coffee
@@ -3,28 +3,29 @@
 #==============================================================================
 describe 'preprocessor', ->
   mocks = require 'mocks'
+  di = require 'di'

-  m = pp = mockFs = doneSpy = fakePreprocessor = null
+  m = pp = mockFs = fakePreprocessor = null

   beforeEach ->
     mockFs = mocks.fs.create
       some:
         'a.js': mocks.fs.file 0, 'originalContent'
-
-
-  it 'should preprocess matching file', (done) ->
-    fakePreprocessor = sinon.spy (content, file, basePath, done) ->
-      file.path = file.path + '-preprocessed'
-      file.contentPath = '/some/new.js'
-      done 'new-content'
+    injector = new di.Injector [{'preprocessor:fake': ['factory', -> fakePreprocessor]}]

     mocks_ =
       fs: mockFs
       minimatch: require 'minimatch'
-      './preprocessors/Coffee': fakePreprocessor
-
+
     m = mocks.loadFile __dirname + '/../../lib/preprocessor.js', mocks_
-    pp = m.createPreprocessor {'**/*.js': 'coffee'}, null
+    pp = m.createPreprocessor {'**/*.js': 'fake'}, null, injector
+
+
+  it 'should preprocess matching file', (done) ->
+    fakePreprocessor = sinon.spy (content, file, done) ->
+      file.path = file.path + '-preprocessed'
+      file.contentPath = '/some/new.js'
+      done 'new-content'

     file = {originalPath: '/some/a.js', path: 'path'}

@@ -34,17 +35,10 @@
       expect(mockFs.readFileSync('/some/new.js').toString()).to.equal 'new-content'
       done()

+
   it 'should ignore not matching file', (done) ->
-    fakePreprocessor = sinon.spy (content, file, basePath, done) ->
+    fakePreprocessor = sinon.spy (content, file, done) ->
       done ''
-
-    mocks_ =
-      fs: mockFs
-      minimatch: require 'minimatch'
-      './preprocessors/Coffee': fakePreprocessor
-
-    m = mocks.loadFile __dirname + '/../../lib/preprocessor.js', mocks_
-    pp = m.createPreprocessor {'**/*.js': 'coffee'}, null

     file = {originalPath: '/some/a.txt', path: 'path'}


Better ordering by score

Better ordering by score

--- src/index.coffee
+++ src/index.coffee
@@ -168,7 +168,7 @@
       next err
     else
       # Sort by descending score
-      scored = _.sortByOrder scored, ["score"], [false]
+      scored = _.orderBy scored, ["score"], ["desc"]
       # Take only top 20
       scored = scored.slice 0, 20
       scored = _.map scored, (post) ->


* [bug] Value inspect should call the _toObject() instead of valueOf()

--- src/index.coffee
+++ src/index.coffee
@@ -97,7 +97,7 @@
     result = @toJSON(aOptions)
     JSON.stringify result
   inspect: ->
-    '<type '+@$type._inspect(value:@valueOf())+'>'
+    '<type '+@$type._inspect(value:@_toObject())+'>'
 #End Value class

 module.exports  = class Type


added result and error to promise

added result and error to promise

--- src/index.coffee
+++ src/index.coffee
@@ -141,6 +141,9 @@
     # @private
     ###
     couchbase_callback = (err, result) ->
+      def.promise.cbError = err
+      def.promise.cbResult = result
+
       # Trace insertion
       if options.trace
         console.log "  - method:"


Some cleanup

Some cleanup

--- src/index.coffee
+++ src/index.coffee
@@ -18,6 +18,18 @@
 query_mapping = assign {}, filter_mapping, expression: 'KeyConditionExpression', index: 'IndexName', limit: 'Limit', forward: 'ScanIndexForward'
 scan_mapping = assign {}, filter_mapping, limit: 'Limit'

+_apply_timestamps = (item) ->
+  now = new Date()
+  item.created_at = now unless item.created_at?
+  item.updated_at = now
+  item
+
+_apply_identifier = (item) ->
+  item.identifier = keygen.url @key_size unless item.identifier?
+  item
+
+
+
 class Model

   constructor: (@name, extension={}) ->
@@ -27,8 +39,8 @@

   put: (item, params={}) ->
     item = assign {}, item
-    @_apply_timestamps item
-    @_apply_identifier item
+    _apply_timestamps item if @auto_timestamps
+    _apply_identifier item if @hash_key == 'identifier'
     params = map_parameters params, condition_mapping
     params.Item = item
     @_request('put', params).then (result) ->
@@ -38,15 +50,15 @@
     params = RequestItems: {}
     items = map items, (item) =>
       item = assign {}, item
-      @_apply_timestamps item
-      @_apply_identifier item
+      _apply_timestamps item if @auto_timestamps
+      _apply_identifier item if @hash_key == 'identifier'
     params.RequestItems[@name] = (PutRequest: Item: item for item in items)
     @_request('batchWrite', params, false).then (results) ->
       items

   insert: (item, params={}) ->
     item = assign {}, item
-    @_apply_identifier item
+    _apply_identifier item
     params.condition = 'identifier <> :identifier'
     params.values =  ':identifier': item.identifier
     @put item, params
@@ -103,18 +115,6 @@

   _key_for: (key) -> key_for key, @hash_key, @range_key

-  _apply_timestamps: (item) ->
-    return item unless @auto_timestamps
-    now = new Date()
-    item.created_at = now unless item.created_at?
-    item.updated_at = now
-    item
-
-  _apply_identifier: (item) ->
-    return item unless @hash_key == 'identifier'
-    item.identifier = keygen.url @key_size unless item.identifier?
-    item
-
   _keyed_params: (keys, params, mapping) ->
     [key, params] = key_and_params keys, params
     params = map_parameters params, mapping


Fix open args

Fix open args

--- src/index.coffee
+++ src/index.coffee
@@ -68,7 +68,7 @@
   # Send the request. Since old versions of IE will fail on UTF8 paths, we
   # try to intelligently escape the URL (being careful not to double escape
   # anything).
-  xhr.open method, url.replace /[^%]+/g, (s) -> encodeURI s
+  xhr.open opts.method, opts.url.replace /[^%]+/g, (s) -> encodeURI s
   xhr.send()


search and without working

search and without working

--- src/index.coffee
+++ src/index.coffee
@@ -10,11 +10,12 @@
 module.exports = (options) ->

 	folders = []
+	only = null
+	without = null
+	search = ['./node_modules/']

 	if valid options.search
 		{search} = options
-	else
-		search = ['./node_modules/']

 	if valid options.only
 		{only} = options
@@ -25,15 +26,19 @@
 	for onePath in search
 		folders.push fs.readdirSync path.resolve onePath

-	modules = zipObject search, folders
+	for moduleGroups in folders
+		if without
+			for one in without
+				moduleGroups.drop one
+		for oneModule in moduleGroups
+			if oneModule is '.bin' or oneModule is 'auto-require'
+				moduleGroups.drop oneModule

-	for k, v of modules
-		v.drop '.bin'
-		v.drop 'auto-require'
+	modulesMap = zipObject search, folders

-	console.log modules
+	console.log modulesMap

 module.exports
 	search: ['./node_modules/', './test/my-modules/']
-	without: ['gulp', 'run-sequence']
-	only: ['grunt']+	without: ['gulp', 'run-sequence', 'chalk']
+	only: ['grunt', 'gulp']


Fix call script from index.coffee

Fix call script from index.coffee

--- src/index.coffee
+++ src/index.coffee
@@ -1,2 +1,2 @@
 module.exports = (robot) ->
-  robot.loadFile __dirname, "script.js"
+  robot.loadFile __dirname, "script.coffee"


Create bulk torrent fixtures.

Create bulk torrent fixtures.

--- app/scripts/models/torrent_model.coffee
+++ app/scripts/models/torrent_model.coffee
@@ -3,22 +3,14 @@
 # Probably should be mixed-in...
 Syrup.Torrent.reopen
     attributes: (->
-        model = @;
+        model = @
         Ember.keys(@get 'data').map( (key)->
-            Em.Object.create(model: model, key: key, valueBinding: 'model.' + key);
+            Em.Object.create(model: model, key: key, valueBinding: 'model.' + key)
         )
     ).property()

-Syrup.Torrent.FIXTURES = [

-  {
-    id: 0,
+Syrup.Torrent.FIXTURES = []

-  },
-
-  {
-    id: 1,
-
-  }
-
-];
+for num in [1..100]
+    Syrup.Torrent.FIXTURES[num] = {id: num}


Stop using the 'isType' module

Stop using the 'isType' module

--- src/index.coffee
+++ src/index.coffee
@@ -5,7 +5,6 @@
 setProto = require "setProto"
 Promise = require "Promise"
 express = require "express"
-isType = require "isType"
 path = require "path"
 now = require "performance-now"
 log = require "log"
@@ -82,7 +81,7 @@
       return if ++index is length
       startTime = now()
       result = pipes[index].call context, req, res
-      if result and isType result.then, Function
+      if result and typeof result.then is "function"
       then result.then done
       else done result

@@ -93,7 +92,7 @@
       return if res._headerSent
       return next() unless result

-      if isType result, Object
+      if result.constructor is Object
         return res.send result

       if result instanceof Error


now crediting Rambda for arity

now crediting Rambda for arity

--- src/index.coffee
+++ src/index.coffee
@@ -4,6 +4,7 @@

 wrap = (x) -> -> x

+# Based on _arity from Rambda: https://github.com/ramda/ramda/blob/v0.26.1/source/internal/_arity.js
 arity  = (N, f) ->
   switch N
     when 0 then  -> f.apply @, arguments


fix multiple servers bug

fix multiple servers bug

--- src/index.coffee
+++ src/index.coffee
@@ -7,7 +7,6 @@
 connect = require("connect")
 liveReload = require("connect-livereload")
 tiny_lr = require("tiny-lr")
-lr = undefined
 apps = []

 http2 = undefined
@@ -28,6 +27,7 @@
     @oldMethod("open") if options.open
     @sockets = []
     @app = undefined
+    @lr = undefined
     @run()

   run: ->
@@ -103,13 +103,13 @@
         if @livereload
           tiny_lr.Server::error = ->
           if @https
-            lr = tiny_lr
+            @lr = tiny_lr
               key: @https.key || fs.readFileSync __dirname + '/certs/server.key'
               cert: @https.cert || fs.readFileSync __dirname + '/certs/server.crt'
           else
-            lr = tiny_lr()
+            @lr = tiny_lr()

-          lr.listen @livereload.port
+          @lr.listen @livereload.port
           @log "LiveReload started on port #{@livereload.port}"

   handlers: ->
@@ -153,11 +153,10 @@
   reload: ->
     es.map (file, callback) ->
       apps.forEach (app) =>
-        if app.livereload and typeof lr == "object"
-          lr.changed body:
+        if app.livereload and typeof app.lr == "object"
+          app.lr.changed body:
             files: file.path
       callback null, file
-  lr: lr
   serverClose: ->
     apps.forEach((app) -> do app.server.close)
     apps = []


Fix double tool loading

Fix double tool loading

--- src/index.coffee
+++ src/index.coffee
@@ -84,10 +84,11 @@
       return
     callback = if tools.length is 1 then cb else loadScripts
     tool = tools.pop()
-    console.log ((isScriptLoaded tool) or (isScriptLoaded Ubret.Dependencies[tool].symbol))
     unless (isScriptLoaded tool) or (isScriptLoaded Ubret.Dependencies[tool].symbol)
       source = Ubret.Dependencies[tool].source
       loadScript source, callback
+    else
+      loadScripts()

   tools = tools.concat findDeps(tools, [])
   loadScripts()


Assets detect changes turn of on production env; better recognition of assets files

--- src/index.coffee
+++ src/index.coffee
@@ -8,7 +8,7 @@
 #

 app = express() # Create Express
-app.use assets() # Add Connect Assets
+app.use assets(detectChanges: not (process.env.NODE_ENV == 'production')) # Add Connect Assets
 app.use express.static(process.cwd() + '/public') # Set the public folder as static assets
 app.set 'view engine', 'jade' # Set View Engine

@@ -28,8 +28,8 @@
 i18n.registerAppHelper app # Register tempalte helper
 app.use i18n.handle # Run i18n as handle

-app.get '/assets/:file', (req, res) -> # Set static path for multilanguage assets
-  file = req.params.file
+app.get '/assets/*', (req, res) -> # Set static path for multilanguage assets
+  file = req.params[0]
   lng = i18n.lng()

   #check if file exists


refactored magnitude to use length

refactored magnitude to use length

--- src/point.coffee
+++ src/point.coffee
@@ -115,7 +115,7 @@
     @type Number
     ###
     magnitude: ->
-      Point.distance(Point(0, 0), this)
+      this.length()

     ###*
     Returns the direction in radians of this point from the origin.


kite: remove log statements

kite: remove log statements

--- node_modules_koding/koding-kite/kite.coffee
+++ node_modules_koding/koding-kite/kite.coffee
@@ -40,24 +40,18 @@
     token = jwt.decode key

     if not token.verify @keys[token.claim.iss]  # Issuer
-      console.log 1
       return false

     if token.claim.aud is not kite.uuid  # Audience
-      console.log 2
       return false

     now = new Date

     exp = new Date(token.claim.exp * 1000)  # Expiration Time
-    console.log exp
-    console.log now
     if exp < now
-      console.log 3
       return false

     if token.claim.nbf * 1000 > now  # Not before
-      console.log 4
       return false

     request.username = token.claim.sub  # Username


Sane event names

Sane event names

--- src/quest.coffee
+++ src/quest.coffee
@@ -92,19 +92,19 @@

     @registerPlugins()

-    @emit "connecting", @client
+    @emit "connectStart", @client
     @client.connect (err) =>
       if err
-        @emit 'connection-error', err
+        @emit 'connectionError', err
         console.error "Couldn't connect!".red.bold
         console.error err.message.red
       else
-        @emit "adventuring"
+        @emit "adventureStart"
         Sync (=> @adventure()), (err, result) =>
           @client.end()
-          @emit 'adventure-finished', result
+          @emit 'adventureFinish', result
           if err or @silentErrors
-            @emit 'adventure-error', err
+            @emit 'adventureError', err
             console.error "Errors occurred!".red.bold
             console.error err.message.red.underline if err
             console.error()
@@ -212,10 +212,13 @@
     opts.times ?= 10
     opts.silent ?= false
     error = null
-    @emit 'retry-loop', opts
+    @emit 'retryLoopStart', opts
     while opts.times > 0
+      @emit 'retry', opts
       try
-        return cb()
+        result = cb()
+        @emit 'retryLoopFinish', opts, result
+        result
       catch e
         error = e
         console.trace e
@@ -226,12 +229,12 @@
           console.log "Retries remaining: #{opts.times}".red.bold
           Sync.sleep(opts.wait)
           opts.times -= 1
-          @emit 'retrying', opts
         else
           throw e

     # Out of lives, time to give up...
     console.error "Out of lives... I give up.".red.underline
+    @emit 'retryLoopFail', opts, error
     if opts.silent
       @silentErrors = true
       console.error e.message.red.underline
@@ -328,27 +331,27 @@
     params ?= []
     queries = render rawQueries ? queries, view
     if split
-      @emit 'splitting', queries, view
+      @emit 'splitStart', queries, view
       queries = new Splitter(@splitter).split queries
-      @emit 'split-complete', queries, view
+      @emit 'splitFinish', queries, view
     result = null
     count = queries.length
     time 'Total Execution Time', =>
-      @emit 'executing-queries', queries, view
+      @emit 'stepStart', queries, view
       for i, query of queries
         i = parseInt(i)
         counter = i
         console.log "\nNow executing #{counter+1} of #{count}"
         console.log "\n#{query}\n".green
-        @emit 'executing-query', i, query
+        @emit 'queryStart', i, query
         if cb?
           @client.query(query, params, cb)
         else
           if @time
             result = time 'Execution Time', =>
               @client.query.sync(@client, query, params)
-        @emit 'executed-query', i, query
+        @emit 'queryFinish', i, query
         console.log()
-      @emit 'executed-queries', queries, view
+      @emit 'stepFinish', queries, view
       console.log()
     result


Added attribution

Added attribution

--- src/queue.coffee
+++ src/queue.coffee
@@ -5,6 +5,7 @@

 	'use strict'

+	# Based on http://tomswitzer.net/2011/02/super-simple-javascript-queue/
 	Queue = ->

 		first = 0


Exports to the bottom

Exports to the bottom

--- src/range.coffee
+++ src/range.coffee
@@ -11,7 +11,7 @@
 TEXT_NODE = 3

-exports.splitBoundaries = splitBoundaries = (range) ->
+splitBoundaries = (range) ->
   {startContainer, startOffset, endContainer, endOffset} = range

   if isTextNode(endContainer)
@@ -30,7 +30,7 @@

 # Public: Creates a wrapper around a range object obtained from a DOMSelection.
-exports.BrowserRange = class BrowserRange
+class BrowserRange

   # Public: Creates an instance of BrowserRange.
   #
@@ -124,7 +124,7 @@
 # Public: A normalised range is most commonly used throughout the annotator.
 # its the result of a deserialised SerializedRange or a BrowserRange with
 # out browser inconsistencies.
-exports.NormalizedRange = class NormalizedRange
+class NormalizedRange

   # Public: Creates an instance of a NormalizedRange.
   #
@@ -252,7 +252,7 @@
     return textNodes[start..end]

 # Public: A range suitable for storing in local storage or serializing to JSON.
-exports.SerializedRange = class SerializedRange
+class SerializedRange

   # Public: Creates a SerializedRange
   #
@@ -419,3 +419,12 @@
   while node? and not contains(node, other)
     node = node.parentNode
   return node
+
+
+# Export the public module interface.
+module.exports = {
+  BrowserRange
+  NormalizedRange
+  SerializedRange
+  splitBoundaries
+}


Hide loading spinner at the bottom of a fair booth feed.

--- apps/fair/components/booths/view.coffee
+++ apps/fair/components/booths/view.coffee
@@ -63,7 +63,7 @@
     )

   renderShows: (items) =>
-    return @$('#fair-browse-spinner').hide() unless items.models.length > 0
+    return @$('#fair-booths-spinner').hide() unless items.models.length > 0
     items.urlRoot = @shows.url
     @feedView?.destroy()
     @feedView = new ShowsFeed
@@ -72,7 +72,7 @@
       additionalParams: @params.toJSON()
       hideSeeMoreButtons: (if @params.get('artist') then true else false)
     @feedView.feedName = 'Fair Feed'
-    @$('#fair-browse-spinner').show()
+    @$('#fair-booths-spinner').hide()

   toggleBoothCount: =>
     @$('.fair-booths-count-container')[if @params.get('section') then 'hide' else 'show']()


Store the server created by connect

Store the server created by connect

--- src/robot.coffee
+++ src/robot.coffee
@@ -200,7 +200,7 @@
           @logger.debug "Registered route: DELETE #{route}"
           app.delete route, callback

-    @connect.listen process.env.PORT || 8080
+    @server = @connect.listen process.env.PORT || 8080

     herokuUrl = process.env.HEROKU_URL


Imperfectly imitate Unix's case-insensitivity.

--- browser/frontend.coffee
+++ browser/frontend.coffee
@@ -6,7 +6,15 @@
 rs = null

 # convenience functions for reading files from localStorage.
-save_file = (fname, data) -> localStorage["file::#{fname}"] = data
+save_file = (fname, data) ->
+  # inefficient but whatever
+  lower = "file::#{fname.toLowerCase()}"
+  for i in [0...localStorage.length] by 1
+    key = localStorage.key(i)
+    if key.toLowerCase() is lower
+      localStorage.removeItem key
+      break
+  localStorage["file::#{fname}"] = data
 load_file = (fname) -> localStorage["file::#{fname}"]
 delete_file = (fname) -> localStorage.removeItem "file::#{fname}"

@@ -180,8 +188,10 @@
     if args.length is 1 then commandCompletions args[0]
     else fileNameCompletions args[0], args
   )
-  additionalText = prefix.substr(_.last(args).length)
-  controller.promptText(promptText + additionalText)
+  return if prefix == ''
+  # delete existing text so we can do case correction
+  promptText = promptText.substr(0, promptText.length - _.last(args).length)
+  controller.promptText(promptText + prefix)

 commandCompletions = (cmd) ->
   (name for name, handler of commands when name.substr(0, cmd.length) is cmd)
@@ -193,14 +203,14 @@
     else if cmd is 'javap' or cmd is 'java' then ext is 'class'
     else true
   keepExt = -> return cmd isnt 'javap' and cmd isnt 'java'
-  lastArg = _.last(args)
+  lastArg = _.last(args).toLowerCase()
   potentialCompletions = []
   for i in [0...localStorage.length] by 1
     key = localStorage.key(i)
     continue unless key.substr(0, 6) is 'file::'
     fname = key.substr(6)
     continue unless validExtension(fname)
-    if (fname.substr(0, lastArg.length) is lastArg)
+    if (fname.substr(0, lastArg.length).toLowerCase() is lastArg)
       potentialCompletions.push(
         if not keepExt() then fname.split('.')[0]
         else fname
@@ -212,8 +222,9 @@
   prefix = lst[0]
   # slow, but should be fine with our small number of completions
   for word in lst
+    lower = word.toLowerCase()
     for c, idx in prefix
-      if (c isnt word[idx])
+      if (c.toLowerCase() isnt lower[idx])
         prefix = prefix.substr(0, idx)
         break
   prefix


Beautify on save

Beautify on save

Former-commit-id: 722a12e321013d8f147f0fd92c36bc1798cc2ec2