Improve coding style

Improve coding style

--- views/components/settings/parts/poi-config.cjsx
+++ views/components/settings/parts/poi-config.cjsx
@@ -80,8 +80,8 @@
       if err?
         toggleModal '删除 Cookies', "删除失败，你可以手动删除 #{path.join(APPDATA_PATH, 'Cookies')}"
         try
-            fs.ensureFileSync path.join(APPDATA_PATH, '')
-            openItem path.join(APPDATA_PATH, '')
+            fs.ensureFileSync APPDATA_PATH
+            openItem APPDATA_PATH
         catch e
             toggleModal '打开缓存目录','打开失败，可能没有访问权限'
       else
@@ -95,8 +95,8 @@
         if error
           toggleModal '删除浏览器缓存', "删除失败，你可以手动删除 #{path.join(APPDATA_PATH, 'Cache')} 和 #{path.join(APPDATA_PATH, 'Pepper Data')}"
           try
-            fs.ensureFileSync path.join(APPDATA_PATH, '')
-            openItem path.join(APPDATA_PATH, '')
+            fs.ensureFileSync APPDATA_PATH
+            openItem APPDATA_PATH
           catch e
             toggleModal '打开缓存目录','打开失败，可能没有访问权限'
         else


remove upgrade notice

remove upgrade notice

Former-commit-id: ac0a297077e91d4c8660ba1fdaaba133d15d1561 [formerly b30178451480b812e75fa21592e3183b101c36ea] [formerly 8a4f49ce56edd089cf5e44f1f341634598fb7aa6 [formerly 8d468b1a8b34240a7be108b1e829c5d4bc9e30a5]] [formerly 512c8279b1a3309e450d9e21e55a31722994a3ed [formerly 253c9f9d7b64f4ce9fee49e9fbce159d354bdff3] [formerly 1c4685535bfcb421b55f812ac0ca95c2dd0c5d3e [formerly 1c4685535bfcb421b55f812ac0ca95c2dd0c5d3e [formerly e34fbec5b75ca91e86a12cc3964d99838c7ef55e]]]]
Former-commit-id: 64cf8af416d3f416851c54b5aebd71e6655a7e63 [formerly db21d727712c764a6d30804b42aa9890502fab19] [formerly 2f522fc97c16a04cf8873dcf7b424a41e5f6392f [formerly 7045158c53c1e4499b0fd9f4163e7b85420138a2]]
Former-commit-id: e2cc48b49e66670f1b3acc30f269cc45f7dd4a0d [formerly 3c3882b3e3713533d73b584a2b90d90199f45570]
Former-commit-id: 17cfb8819c81e09dcf75b3cd10fe2105ad9b067b
Former-commit-id: 131b92729d9bf647ad529f7fa26ffd7808fdc2aa

--- @client/header.coffee
+++ @client/header.coffee
@@ -14,14 +14,14 @@

     DIV null,
-      DIV
-        style:
-          backgroundColor: logo_red
-          textAlign: 'center'
-          color: 'white'
-          padding: 15
-
-        "Consider.it will be down from approximately 3:30pm - 4:30pm PT Today, 1/15, for server upgrades."
+      # DIV
+      #   style:
+      #     backgroundColor: logo_red
+      #     textAlign: 'center'
+      #     color: 'white'
+      #     padding: 15
+
+      #   "Consider.it will be down from approximately 3:30pm - 4:30pm PT Today, 1/15, for server upgrades."

       DIV
         style:


Sidebar: Added removeMachineNode method.

--- client/Social/Activity/sidebar/activitysidebar.coffee
+++ client/Social/Activity/sidebar/activitysidebar.coffee
@@ -821,3 +821,11 @@
         ws for ws in KD.userWorkspaces when ws.machineUId isnt machine.uid

       @updateMachineTree()
+
+
+  removeMachineNode: (machine) ->
+    {nodes}    = @machineTree
+    {jMachine} = machine
+
+    for nodeId, node of nodes when node.data?.jMachine is jMachine
+      @machineTree.removeNode nodeId


add cookies-js

add cookies-js

--- components/auth_modal/view.coffee
+++ components/auth_modal/view.coffee
@@ -1,6 +1,7 @@
 _ = require 'underscore'
 Backbone = require 'backbone'
 { parse } = require 'url'
+Cookies = require 'cookies-js'
 ModalView = require '../modal/view.coffee'
 Form = require '../mixins/form.coffee'
 mediator = require '../../lib/mediator.coffee'


Remove `format`

Remove `format`

--- src/request.coffee
+++ src/request.coffee
@@ -4,7 +4,6 @@
   DEFAULTS =
     url: null
     method: "GET"
-    format: "json"
     async: true
     data: null


Fix twitch requests

Fix twitch requests

--- src/request.coffee
+++ src/request.coffee
@@ -31,7 +31,7 @@
     )

 exports.getJSON = getJSON = (url, options = {}) ->
-    return request(url).then((res) ->
+    return request(url, options).then((res) ->
         switch res.statusCode
             when 400, 403, 404, 500, 503 then \
                 if not options.skipStatusCheck or


Restart phantom process if crashes

Restart phantom process if crashes

--- src/coffee/routes.coffee
+++ src/coffee/routes.coffee
@@ -40,21 +40,28 @@
     loadPdf fileName, res, (data) ->
       res.status(200).download filePath(fileName), fileName

+
+
   app.all '*', (req, res, next) ->
     if _ph
       logger.debug 'Phantom process already running, skipping...'
       next()
     else unless _phIsStarting
-      _phIsStarting = true
-      phantomOpts =
-        port: (port - 1)
-      phantom.create "--web-security=no", "--ignore-ssl-errors=yes",
-        phantomOpts
-      , (ph) ->
-        _ph = ph
-        _phIsStarting = false
-        logger.info "New phantom process created on port #{phantomOpts.port}"
-        next()
+      createPhantomProcess = ->
+        _phIsStarting = true
+        phantomOpts =
+          port: (port - 1)
+          onExit: ->
+            logger.error 'Phantom process exited unexpectedly or crashed. Will try to spawn up a new process...'
+            createPhantomProcess()
+        phantom.create "--web-security=no", "--ignore-ssl-errors=yes",
+          phantomOpts
+        , (ph) ->
+          _ph = ph
+          _phIsStarting = false
+          logger.info "New phantom process created on port #{phantomOpts.port}"
+          next()
+      createPhantomProcess()

   # homepage
   app.get '/', (req, res, next) ->


allow multiple patterns to match files

allow multiple patterns to match files

--- src/sitemap.coffee
+++ src/sitemap.coffee
@@ -45,7 +45,7 @@
 		priority = (@data.priority or 0.5).toString()

 		# File pattern
-		pattern = path.join root, (@data.pattern or '/**/*.html')
+		pattern = this.data.pattern or path.join root, '/**/*.html'

 		# Glob root
 		files = grunt.file.expand pattern


get improved implementation from dropped 'plugins' branch

--- lib/relistener.coffee
+++ lib/relistener.coffee
@@ -1,12 +1,38 @@
 module.exports = ->

-  listen = @listen ? -> console.log 'Listening on',server.address()
+  # alias
+  server = @server
+
+  # if they didn't specify a relisten function, then, we'll change listen()
+  # to remember its args so we can reuse them.
+  unless @relisten?
+    # remember the args in this var
+    listenArgs = null
+
+    # remember the original function (let's just put it right on it...)
+    server.originalListen = server.listen
+
+    # replace `listen()` with our function
+    server.listen = (args...) ->
+      listenArgs = args
+
+      # let's avoid adding the listening callback multiple times
+      # so, if the last arg is a callback...
+      if typeof listenArgs[listenArgs.length - 1] is 'function'
+
+        # make a copy of the args array so we can change it
+        # and remove the function at the same time
+        listenArgs = listenArgs[...-1]
+
+      # now make the real listen() call with their args
+      server.originalListen args...
+
+    # create our `relisten()` which calls the real listen() with the args we
+    # remembered from them calling listen()
+    relisten = -> server.originalListen listenArgs...

   retryDelay = @retryDelay ? 3000
   maxRetries = @maxRetries ? 3
-
-  # alias
-  server = @server

   # start out with zero retries
   server.inUseRetryCount = 0
@@ -21,7 +47,7 @@
       if server.inUseRetryCount < maxRetries

         # notify them
-        console.error 'Address in use, retrying in 3 seconds...'
+        console.error 'Address in use, retrying in', (retryDelay / 1000), 'seconds...'

         # remember we tried
         server.inUseRetryCount++
@@ -29,7 +55,9 @@
         # retry in a bit
         setTimeout (->
           # call listen() in the callback
-          server.close -> listen()
+          server.close ->
+            server.emit 'relisten'
+            relisten()
         ), retryDelay

         # # could mark we handled this error, for other error listeners...


Use both widths mode in demo

Use both widths mode in demo

--- lib/table-edit.coffee
+++ lib/table-edit.coffee
@@ -40,6 +40,8 @@

   openDemoWithGutter: ->
     tableElement = @getTableView()
+    tableElement.setAbsoluteColumnsWidths(true)
+
     tableElement.showGutter()

   getTableView: ->
@@ -58,7 +60,6 @@
     table.clearUndoStack()

     tableElement = atom.views.getView(table)
-    tableElement.absoluteColumnsWidths = true
     tableElement.setRowHeightAt(3, 90)
     tableElement.setRowHeightAt(30, 110)
     tableElement.setRowHeightAt(60, 60)


patch for history changes

patch for history changes

--- lib/ui/console.coffee
+++ lib/ui/console.coffee
@@ -39,7 +39,7 @@
     if ed.getText()
       comm.withClient =>
         @c.done()
-        comm.msg 'eval-repl', {code: ed.getText(), mode: ed.inkConsoleMode}, (result) =>
+        comm.msg 'eval-repl', {code: ed.getText(), mode: ed.inkConsoleMode?.name}, (result) =>
           @c.input()
           notifications.show "Evaluation Finished"


log console history

log console history

--- lib/ui/console.coffee
+++ lib/ui/console.coffee
@@ -49,6 +49,7 @@
   eval: (ed) ->
     if ed.getText().trim()
       @client.boot()
+      @c.logInput()
       @c.done()
       @client.rpc('evalrepl', code: ed.getText(), mode: ed.inkConsoleMode?.name)
         .then (result) =>


Exclude trash=true, not require trash=false

--- lib/www_routes.coffee
+++ lib/www_routes.coffee
@@ -481,7 +481,7 @@
         (done) ->
           schema.SearchIndex.find({
             'sharing.group_id': doc._id
-            'trash': false
+            'trash': {$ne: true}
           }).sort('-modified').exec done

         (done) ->


Space after period.

Space after period.

--- patten.coffee
+++ patten.coffee
@@ -681,7 +681,7 @@
     if success
         bitcoin.getTransaction(txid, (tx) ->
             amount = tx.amount / bitcoin.BTC_IN_SATOSHI
-            alert("Thanks! #{amount} BTC was just sent to user #{login_data.name}." +
+            alert("Thanks! #{amount} BTC was just sent to user #{login_data.name}. " +
                   "Now you just need to wait for 1 confirmation.")
         )


Fix a typo

Fix a typo

--- main.coffee
+++ main.coffee
@@ -66,7 +66,7 @@
             console.info @format 'info', texts

     warn: (texts...) ->
-        if process.env.DEBUG or pprocess.env.NODE_ENV isnt 'test'
+        if process.env.DEBUG or process.env.NODE_ENV isnt 'test'
             console.info @format 'warn', texts
             console.warn @format 'warn', texts


Keep showLinkText local for link hints.

Keep showLinkText local for link hints.

We only need showLinkText in the hint's local frame, so do not transmit
it to remote frames.

--- content_scripts/link_hints.coffee
+++ content_scripts/link_hints.coffee
@@ -79,8 +79,8 @@
       @localHints = LocalHints.getLocalHints()
       console.log "getHintDescriptors", frameId, "[#{@localHints.length}]" if @debug
       @sendMessage "postHintDescriptors", hintDescriptors:
-        @localHints.map ({linkText, showLinkText, hasHref}, localIndex) ->
-          {linkText, showLinkText, hasHref, frameId, localIndex}
+        @localHints.map ({linkText, hasHref}, localIndex) ->
+          {linkText, hasHref, frameId, localIndex}

   # We activate LinkHintsMode() in every frame and provide every frame with exactly the same hint descriptors.
   # We also propagate the key state between frames.  Therefore, the hint-selection process proceeds in lock
@@ -187,19 +187,22 @@
   createMarkerFor: (desc) ->
     marker =
       if desc.frameId == frameId
+        localHintDescriptor = HintCoordinator.getLocalHintMarker desc
         el = DomUtils.createElement "div"
-        el.rect = HintCoordinator.getLocalHintMarker(desc).rect
+        el.rect = localHintDescriptor.rect
         el.style.left = el.rect.left + window.scrollX + "px"
         el.style.top = el.rect.top  + window.scrollY  + "px"
-        extend el, className: "vimiumReset internalVimiumHintMarker vimiumHintMarker"
+        extend el,
+          className: "vimiumReset internalVimiumHintMarker vimiumHintMarker"
+          showLinkText: localHintDescriptor.showLinkText
+          localHintDescriptor: localHintDescriptor
       else
         {}

     extend marker,
       hintDescriptor: desc
+      isLocalMarker: desc.frameId == frameId
       linkText: desc.linkText
-      showLinkText: desc.showLinkText
-      isLocalMarker: desc.frameId == frameId
       stableSortCount: ++@stableSortCount

   # Handles <Shift> and <Ctrl>.
@@ -295,10 +298,10 @@
   # selectively pushing the appropriate HintCoordinator.onExit handlers.
   activateLink: (linkMatched, userMightOverType=false) ->
     @removeHintMarkers()
-    localHintDescriptor = HintCoordinator.getLocalHintMarker linkMatched.hintDescriptor
-    clickEl = localHintDescriptor?.element
-
-    if clickEl?
+
+    if linkMatched.isLocalMarker
+      localHintDescriptor = linkMatched.localHintDescriptor
+      clickEl = localHintDescriptor.element
       HintCoordinator.onExit.push (isSuccess) =>
         if isSuccess
           if localHintDescriptor.reason == "Frame."


Added Player#completeLine

Added Player#completeLine

--- player.coffee
+++ player.coffee
@@ -55,5 +55,8 @@
     addToLine: (pos) ->
       @unverified_positions.push(pos)

+    completeLine: ->
+      @positions.concat(@unverified_positions)
+
   Player
 )


Add new spec on Effector Plugin

Add new spec on Effector Plugin

--- docs/nwdrome_effector_plugin_spec.coffee
+++ docs/nwdrome_effector_plugin_spec.coffee
@@ -56,7 +56,8 @@
         onResize    : (width, height) ->
             # Be notified of canvas size change.

-        onTimer     : ->
+        # @param HTMLCanvasElement[]  plugin destination canvases.
+        onTimer     : (activePluginDestination)->
             # Call from nwdrome when requestAnimationFrame fired.
             # Will rendering process write here.


Converted dashboard data fetcher to coffee

--- dashboard_spec.coffee
+++ dashboard_spec.coffee
@@ -3,8 +3,8 @@

 describe "Dashboard - getData()", ->
   beforeEach ->
+    jasmine.Ajax.useMock()
     @dashboard = Dashboard
-    jasmine.Ajax.useMock()

   describe "when the report is ready on the first iteration", ->
     it "should return the dashboard data", ->
@@ -22,6 +22,8 @@

       runs ->
         request = mostRecentAjaxRequest()
+        expect(request.url).toBe('/dashboard/queries/REPORT_ID/ready')
+        expect(request.method).toBe('GET')
         request.response { status: 200, responseText: '{"is_ready": true, "data":"DATA" }' }

         expect(that.data).toEqual 'DATA'


fixes #185

fixes #185

--- chrome/content/zotero-better-bibtex/zotero-better-bibtex.coffee
+++ chrome/content/zotero-better-bibtex/zotero-better-bibtex.coffee
@@ -47,7 +47,7 @@
         when 'library'
           data = { data: true }
         when 'group'
-          data = { data: true, collection: Zotero.Groups.get(collectionsView.getSelectedLibraryID())
+          data = { data: true, collection: Zotero.Groups.get(collectionsView.getSelectedLibraryID()) }

     when 'items'
       data = { data: true, items: pane?.getSelectedItems() }


texnotes

texnotes

--- chrome/content/zotero-better-bibtex/zotero-better-bibtex.coffee
+++ chrome/content/zotero-better-bibtex/zotero-better-bibtex.coffee
@@ -1086,31 +1086,31 @@

   HTMLNode::alias(['pre', 'b', 'p', 'div', 'ul', 'li'])

-Zotero.BetterBibTeX.pandoc = new class
-  constructor: ->
-    env = Components.classes["@mozilla.org/process/environment;1"].getService(Components.interfaces.nsIEnvironment)
-
-    if env.exists('PATH')
-      @searchpath = env.get('PATH').split((if Zotero.isWin then ';' else ':'))
-    else
-      @searchpath = []
-
-    @executable = 'pandoc'
-    @executable += '.exe' if Zotero.isWin
-
-    @pandoc = null
-    for dir in @searchpath
-      path = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile)
-      path.initWithPath(dir)
-      path.append(@executable)
-      if path.exists()
-        @pandoc = path.path
-        break
-
-  convert: (src, target) ->
-    throw new Error("#{@executable} not found in #{JSON.stringify(@searchpath)}") unless @pandoc
-    return
-
-    path = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile)
-    path.initWithPath(src)
-    path.remove()
+#Zotero.BetterBibTeX.pandoc = new class
+#  constructor: ->
+#    env = Components.classes["@mozilla.org/process/environment;1"].getService(Components.interfaces.nsIEnvironment)
+#
+#    if env.exists('PATH')
+#      @searchpath = env.get('PATH').split((if Zotero.isWin then ';' else ':'))
+#    else
+#      @searchpath = []
+#
+#    @executable = 'pandoc'
+#    @executable += '.exe' if Zotero.isWin
+#
+#    @pandoc = null
+#    for dir in @searchpath
+#      path = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile)
+#      path.initWithPath(dir)
+#      path.append(@executable)
+#      if path.exists()
+#        @pandoc = path.path
+#        break
+#
+#  convert: (src, target) ->
+#    throw new Error("#{@executable} not found in #{JSON.stringify(@searchpath)}") unless @pandoc
+#    return
+#
+#    path = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile)
+#    path.initWithPath(src)
+#    path.remove()


FinderController: unmount the machine first if it’s mounted fixes #11077

--- client/finder/lib/filetree/controllers/nfindercontroller.coffee
+++ client/finder/lib/filetree/controllers/nfindercontroller.coffee
@@ -173,6 +173,10 @@

     computeController.fetchMachine { uid }, (err, machine) =>
       return showError err  if err
+
+      if machineItem = @getMachineNode uid
+        @unmountMachine uid  if machineItem.data.path isnt "[#{uid}]#{path}"
+
       @mountMachine machine


turn off trace

turn off trace

--- elasticsearch.coffee
+++ elasticsearch.coffee
@@ -11,7 +11,7 @@
 esConfig = require('./config.js').elasticsearch
 client = new elasticsearch.Client {
   host: esConfig.host,
-  log: 'trace'
+  #log: 'trace'
 }

 # number of missing files
@@ -148,9 +148,10 @@
             id: gist.id
             body: es
           , (err) ->
-            console.log "indexed", gist.id
+            console.log "indexed~", gist.id
             return gistCb(err)
         else
+          console.log "already", gist.id
           setTimeout ->
             return gistCb()
           , Math.random() * 50 + 50


Even more resilience.

Even more resilience.

--- src/createProject.coffee
+++ src/createProject.coffee
@@ -55,6 +55,7 @@
   [pair[0], iterator pair[1]] for pair in pairs

 makeValues = (varNames, globals, targetDir) ->
+  globals = {} unless globals
   values = {}
   for varName in varNames
     values[varName] = if globals[varName] then globals[varName] else null


Mise à jour des données et fermeture du formulaire lors de la sauvegarde.


Ensure two_finger_gestures execution only when >2 fingers are touching the canvas.

--- engine/events.coffee
+++ engine/events.coffee
@@ -64,6 +64,8 @@
         return touch_events

     two_finger_gestures: ->
+        if @touch.touches < 2
+            return
         touch_events = @get_touch_events()[...2]
         pos1 = @touch.pos1
         pos2 = @touch.pos2
@@ -85,8 +87,6 @@
         vec2.sub(r, pos2, pos1)
         x = r[0]
         y = r[1]
-
-

         if x > 0 # +X
             rot = Math.atan(y/x)


Fixing typo: invalid select.

Fixing typo: invalid select.

--- src/d3.timeslider.coffee
+++ src/d3.timeslider.coffee
@@ -52,7 +52,7 @@

         @useBBox = false
         if @svg[0][0].clientWidth == 0
-            d3.select(element).select('svg')
+            d3.select(@element).select('svg')
                 .append('rect').attr('width', '100%')
                 .attr('height', '100%')
                 .attr('opacity', '0')


fixes

fixes

--- client/front.coffee
+++ client/front.coffee
@@ -110,7 +110,7 @@
         .replace(/</g, '<')
         .replace(/>/g, '>')
         .replace(/"/g, '"') #"
-        .replace(/'/g, ''')
+        .replace(/'/g, ''') #'
         .replace(/\//g,'/');

 # its very simple and stupid
@@ -135,7 +135,7 @@
                     return

     tokenize: (@line, @mode) ->
-        key = @mode+"|"+@line
+        key = @mode + "|" + @line
         if @token_cache[key]
             return @token_cache[key]
         return @token_cache[key] = @tokenize_line()


using tag.name for teks and LO's

using tag.name for teks and LO's

--- src/flux/exercise.coffee
+++ src/flux/exercise.coffee
@@ -5,7 +5,7 @@
 {makeSimpleStore} = require './helpers'

 EXERCISE_TAGS =
-  TEK: 'tek'
+  TEK: 'teks'
   LO: 'lo'
   GENERIC: 'generic'

@@ -49,7 +49,7 @@
       tekTags = _.where(tags, {type: EXERCISE_TAGS.TEK})

       _.reduce(tekTags, (memo, tag) ->
-        memo + " / " + tag.id
+        memo + " / " + tag.name
       , '')

     getContent: (exercise_id) ->
@@ -69,7 +69,7 @@
           tagArr.push(tag.id)
           memo.tagString = tagArr.join(" / ")
         else if (tag.type is EXERCISE_TAGS.LO)
-          memo.lo = tag.id
+          memo.lo = tag.name
           memo.section = tag.chapter_section[0] + '-' + tag.chapter_section[1]
         memo
       , obj)


fix a bug when submitting jumpIn forms on homepage

--- src/frontend/home.coffee
+++ src/frontend/home.coffee
@@ -58,6 +58,13 @@
             left    : '+=290'
         }, 600

+    fireAllBlurOnSubmit : () =>
+        form    = (do @_jqDiv.get).children 'form'
+        btn     = (do @_jqDiv.get).children 'button[type=submit]'
+        btn.click (event) =>
+            (form.find 'input').each () ->
+                ($ @).trigger 'blur'
+
 class ChoiceForm
     constructor : (@name) ->
         @_jqElem    = PrivateValue.GetOnly ($ '#' + @name)
@@ -65,6 +72,9 @@
         (do @_jqForm.get).submit @onSubmit
         for input in ((do @_jqForm.get).find 'input')
             ($ input).bind 'blur', @onFieldBlur
+        do @fireAllBlurOnSubmit
+
+    fireAllBlurOnSubmit : () =>
         ((do @_jqElem.get).find 'button[type=submit]').click (event) =>
             ((do @_jqElem.get).find 'input').each () ->
                 ($ @).trigger 'blur'
@@ -111,13 +121,17 @@

 class JumpInForm extends ChoiceForm
     constructor : (@name) ->
-        super @name
-        @_jqFirstStep   = PrivateValue.GetOnly (do @_jqElem.get).find '#stepOne'
-        @_jqBtn         = PrivateValue.GetOnly (do @_jqFirstStep.get).find 'button'
         @steps  = [
             new JumpInStep this, 'newRoom'
             new JumpInStep this, 'joinRoom'
         ]
+        super @name
+        @_jqFirstStep   = PrivateValue.GetOnly (do @_jqElem.get).find '#stepOne'
+        @_jqBtn         = PrivateValue.GetOnly (do @_jqFirstStep.get).find 'button'
+
+    fireAllBlurOnSubmit : () =>
+        for step in @steps
+            do step.fireAllBlurOnSubmit

     hide : () =>
         (do @_jqFirstStep.get).fadeTo 0.99


remove not necessary method

remove not necessary method


SocialWorker: SocialChannel: remove unused sinkrow imports

--- workers/social/lib/social/models/socialapi/channel.coffee
+++ workers/social/lib/social/models/socialapi/channel.coffee
@@ -1,9 +1,10 @@
+async            = require 'async'
 Bongo            = require 'bongo'
 { Relationship } = require 'jraphical'
 request          = require 'request'
 KodingError      = require '../../error'

-{ secure, daisy, dash, signature, Base } = Bongo
+{ secure, signature, Base } = Bongo
 { throttle } = require 'underscore'

 module.exports = class SocialChannel extends Base


Set borderRadius for @knob to stay circular

--- framer/Components/SliderComponent.coffee
+++ framer/Components/SliderComponent.coffee
@@ -48,7 +48,7 @@
 		@knob.draggable.momentumOptions = {friction: 2, tolerance: 1/10}
 		@knob.draggable.bounce = false
 		@knob.draggable.propagateEvents = false
-		@knob.borderRadius = @knob.width
+		@knob.borderRadius = 100
 		@knob.placeBefore(@fill)

 		@_updateFrame()


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/camera.coffee
+++ test/camera.coffee
@@ -6,6 +6,6 @@
 test "overlay", 1, ->
   object = GameObject()

-
+  c = Came
 # Clear out the module
 module()


restore firefox compile and xpi rules, but still need to fix more

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -23,6 +23,7 @@

 chromeExtDevPath = 'build/dev/chrome/extension/'
 chromeAppDevPath = 'build/dev/chrome/app/'
+firefoxDevPath = 'build/dev/firefox/'

 # TODO: Move this into common-grunt-rules in uproxy-lib.
 Rule.symlink = (dir, dest='') =>
@@ -120,9 +121,9 @@

       firefox_uproxy: {
         files: [ {
-          src: ['build/firefox/data/core/uproxy.js'
-                'build/firefox/lib/exports.js']
-          dest: 'build/firefox/lib/uproxy.js'
+          src: [firefoxDevPath + 'data/core/uproxy.js'
+                firefoxDevPath + 'lib/exports.js']
+          dest: firefoxDevPath + 'lib/uproxy.js'
         } ]
       }

@@ -211,6 +212,56 @@
           dest: chromeAppDevPath
         } ]

+      # Firefox. Assumes the top-level tasks generic_core and generic_ui
+      # completed.
+      firefox:
+        files: [ {
+          # The platform specific stuff, and...
+          expand: true, cwd: 'src/firefox/'
+          src: ['**', '!**/spec', '!**/*.md', '!**/*.ts']
+          dest: firefoxDevPath
+        # }, {
+          # expand: true, cwd: 'build/dev'
+          # src: ['uproxy.js']
+          # dest: firefoxDevPath + 'data/core/'
+        # ... the generic core stuff
+        }, {
+          expand: true, cwd: 'build/dev/generic_core'
+          src: ['**'],
+          dest: firefoxDevPath + 'data/core/'
+        # ... the generic UI stuff
+        }, {
+          expand: true, cwd: 'build/dev/generic_ui'
+          src: ['**'],
+          dest: firefoxDevPath + 'data'
+        }, {
+          expand: true, cwd: 'build/dev', flatten: true
+          src: FILES.uproxy_common,
+          dest: firefoxDevPath + 'data/scripts'
+        # freedom for firefox
+        }, {
+          expand: true, cwd: 'node_modules/uproxy-lib/build/freedom'
+          src: ['freedom-for-firefox-for-uproxy.jsm']
+          dest: firefoxDevPath + 'data'
+        }, {
+        # TODO: Fix socks-rtc / uproxy-networking include?
+          expand: true, cwd: 'node_modules/socks-rtc/build/'
+          src: ['**'],
+          dest: firefoxDevPath + 'data/lib/socks-rtc'
+        }, {
+          expand: true, cwd: 'node_modules/freedom/providers/social'
+          src: ['websocket-server/**']
+          dest: firefoxDevPath + 'data/lib'
+        }, {
+          expand: true, cwd: 'node_modules/freedom-social-xmpp/build/'
+          src: ['**']
+          dest: firefoxDevPath + 'data/lib/freedom-social-xmpp'
+        }, {
+          expand: true, cwd: 'node_modules/freedom/providers/storage/isolated'
+          src: ['**']
+          dest: firefoxDevPath + 'data/lib/storage'
+        } ]
+
     }  # copy

     #-------------------------------------------------------------------------
@@ -299,12 +350,23 @@
           outfile: 'build/dev/generic_ui/_SpecRunner.html'
           keepRunner: true

+    compress:
+      main:
+        options:
+          mode: 'zip'
+          archive: 'dist/uproxy.xpi'
+        expand: true
+        cwd: 'build/dev/firefox'
+        src: ['**']
+        dest: '.'
+
     clean: ['build/**']

  # grunt.initConfig

   #-------------------------------------------------------------------------
   grunt.loadNpmTasks 'grunt-contrib-clean'
+  grunt.loadNpmTasks 'grunt-contrib-compress'
   grunt.loadNpmTasks 'grunt-contrib-concat'
   grunt.loadNpmTasks 'grunt-contrib-copy'
   grunt.loadNpmTasks 'grunt-contrib-jasmine'
@@ -368,7 +430,7 @@
     'build_generic_ui'
     'build_generic_core'
     'typescript:firefox'
-    # 'copy:firefox'
+    'copy:firefox'
   ]

   taskManager.add 'build_firefox_xpi', [


Replacement for simple quote variable

Replacement for simple quote variable

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -108,10 +108,10 @@

 				options:
 					replacements: [
-						pattern: /src="(\.\.\/)?(?!http|\/|\/\/|\#|\&)/ig
+						pattern: /src="(\.\.\/)?(?!http|\/|\/\/|\#|\&|\'\&)/ig
 						replacement: 'src="' + tagApplicationRoot
 					,
-						pattern: /href="(\.\.\/)?(?!http|\/|\/\/|\#|\&)/ig
+						pattern: /href="(\.\.\/)?(?!http|\/|\/\/|\#|\&|\'\&)/ig
 						replacement: 'href="' + tagApplicationRoot
 					,
 						pattern: '<script src="http://localhost:35729/livereload.js"></script>'


Demo script removed from build list

Demo script removed from build list

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -8,7 +8,6 @@
             compile:
                 files:
                     'lib/moon.js': 'src/Moon.coffee'
-                    'demo/lib/js/app.js': ['src/Moon.coffee', 'demo/src/coffee/app.coffee']
                     'tests/lib/js/tests.js': ['src/Moon.coffee', 'tests/src/coffee/tests.coffee']

         uglify:
@@ -38,7 +37,7 @@
                     level: 'error'

-            app: ['demo/**/*.coffee', 'src/**/*.coffee', 'tests/**/*.coffee']
+            app: ['src/**/*.coffee', 'tests/**/*.coffee']

         watch:
             scripts:


feat(grunt): put doc generation to release rather than build

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -44,7 +44,7 @@

     # Clean house
     clean:
-      build: [BUILD_DIR, DOC_DIR]
+      build: [BUILD_DIR]

     # Watch
     watch:
@@ -123,13 +123,13 @@
     'clean'
     'exec:build'
     'copy:404'
-    'docker'
   ]

   # Release -- new version!
   grunt.registerTask 'release', (type) ->
     grunt.task.run [
       "bump-only:#{type or 'patch'}"
+      'docker'
       'changelog'
       'bump-commit'
     ]


Fix Gruntfile.coffee

Fix Gruntfile.coffee

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -37,7 +37,7 @@
                     'libs/angular/*.min.js'
                     'libs/angular-touch/*.min.js'
                     'libs/jquery/*.min.js'
-                    'libs/venturerocket-angular-slider/build/*.min.js'
+                    'libs/venturocket-angular-slider/build/*.min.js'
                     'libs/bootstrap/dist/js/*.min.js'
                     'libs/bootstrap/dist/css/*.min.css'
                     'libs/bootstrap/dist/fonts/*'


Better automatic versioning.

Better automatic versioning.

Signed-off-by: Carlos Escribano <ab5e2bca84933118bbc9d48ffaccce3bac4eeb64@doofinder.com>

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -87,7 +87,9 @@
           prefix: '\"version\":\\s\"'
         src: ['./bower.json']
       project:
-        src: ["package.json"]
+        options:
+          prefix: '\"doofinder\",\\s+\"version\":\\s+\"'
+        src: ["package.json", "package-lock.json"]

     watch:
       default:


Tweak delete button position

Tweak delete button position

--- scripts/controllers/Marker.coffee
+++ scripts/controllers/Marker.coffee
@@ -75,8 +75,8 @@
 		@labelText.attr text: @marking.species.toUpperCase()
 		textBox = @labelText.getBBox()
 		@labelRect.attr width: 20 + Math.round(textBox.width) + 10
-		@deleteButton.transform "T#{@labelRect.attr 'width'},#{-style.crossCircle.r - (style.crossCircle['stroke-width'] / 2)}"
-		@deleteText.transform "T#{@labelRect.attr('width') + 5},0}"
+		@deleteButton.transform "T#{@labelRect.attr('width') - 1},#{-style.crossCircle.r - (style.crossCircle['stroke-width'] / 2)}"
+		@deleteText.transform "T#{@labelRect.attr('width') + 3},-1}"
 		@labelRect.attr fill: style[@marking.species]
 		@deleteButton.attr fill: style[@marking.species]


rebuild index.html when README.md changes

Now that we have the contents of `README.md` in `index.html`, we need it watched as well.

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -24,7 +24,7 @@
         files: ['dist/css/bootstrap.css']
         tasks: ['cssmin:minify']
       assemble:
-        files: ['pages/*.html', 'pages/examples/*']
+        files: ['pages/*.html', 'pages/examples/*', 'README.md']
         tasks: ['assemble']
     cssmin:
       minify:


fixed bump options

fixed bump options

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -11,7 +11,7 @@
 		bump:
 			options:
 				commitMessage: 'chore: release v%VERSION%'
-				pushTo: 'upstream'
+				pushTo: 'origin'

 		'auto-release':
 			options:


style(grunt): capitalize constant PORT

style(grunt): capitalize constant PORT

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -6,7 +6,7 @@
   DOC_DIR = 'doc'

   # Port to use to run the local webserver
-  port = process.env.LOCAL_PORT or 8888
+  PORT = process.env.LOCAL_PORT or 8888

   # Load Grunt tasks
   grunt.loadNpmTasks 'grunt-contrib-clean'
@@ -73,14 +73,14 @@
     brunch:
       serve:
         action: 'serve'
-        port: port
+        port: PORT
       serveAsync:
         action: 'serve'
-        port: port
+        port: PORT
         async: true
       watch:
         action: 'watch'
-        port: port
+        port: PORT
       compile:
         action: 'compile'
       build:


Update test task

Update test task

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -68,8 +68,8 @@
             custom:
                 options: {}
                 src: [
-                    "test/fixtures/default/**/*.coffee"
-                    "test/fixtures/custom"
+                    "test/fixtures/default"
+                    "test/fixtures/custom/**/*.coffee"
                 ]

     grunt.loadTasks "tasks"


Gruntfile: Styling change.

Gruntfile: Styling change.

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -2,16 +2,16 @@

   grunt.initConfig

-    clean            :
-      all            :
-        options      :
-          force      : yes
-        src          : 'build'
+    clean                :
+      all                :
+        options          :
+          force          : yes
+        src              : 'build'

-    mkdir            :
-      all            :
-        options      :
-          create     : [
+    mkdir                :
+      all                :
+        options          :
+          create         : [
             'src/coffee'
             'src/externs'
             'src/images'
@@ -23,98 +23,71 @@
             'build/images'
           ]

-    coffee           :
-      all            :
-        options      :
-          bare       : yes
-        files        : [
-          expand     : yes
-          cwd        : 'src'
-          src        : [ 'coffee/**/*.coffee', 'tests/**/*.coffee' ]
-          dest       : 'build/js/'
-          ext        : '.js'
+    coffee               :
+      all                :
+        options          :
+          bare           : yes
+        files            : [
+          expand         : yes
+          cwd            : 'src'
+          src            : [ 'coffee/**/*.coffee', 'tests/**/*.coffee' ]
+          dest           : 'build/js/'
+          ext            : '.js'
         ]

-    sprites          :
-      all            :
-        files        :
-          src        : 'src/images'
-          dest       : 'build/images'
+    sprites              :
+      all                :
+        files            :
+          src            : 'src/images'
+          dest           : 'build/images'

-    coffee2closure   :
-      all            :
-        files        : [
-          expand     : yes
-          src        : 'build/js/**/*.js'
-          ext        : '.js'
+    coffee2closure       :
+      all                :
+        files            : [
+          expand         : yes
+          src            : 'build/js/**/*.js'
+          ext            : '.js'
         ]

-    stylus           :
-      options        :
-        'include css': true
-        'compress'   : false
-      all            :
-        files        : [
-          expand     : true
-          src        : [ '*.styl' ]
-          ext        : '.css'
-          cwd        : 'src/styl'
-          dest       : 'build/css'
+    stylus               :
+      options            :
+        'include css'    : true
+        'compress'       : false
+      all                :
+        files            : [
+          expand         : true
+          src            : [ '*.styl' ]
+          ext            : '.css'
+          cwd            : 'src/styl'
+          dest           : 'build/css'
         ]

-    templates        :
-      all            :
-        src          : 'src/templates/**/*.soy'
-        dest         : 'build/templates/'
+    templates            :
+      all                :
+        src              : 'src/templates/**/*.soy'
+        dest             : 'build/templates/'

-    deps             :
-      all            :
-        options      :
-          outputFile : 'build/deps.js'
-          prefix     : '../../../../'
-          root       : [
+    deps                 :
+      all                :
+        options          :
+          outputFile     : 'build/deps.js'
+          prefix         : '../../../../'
+          root           : [
             'bower_components/closure-library'
             'bower_components/closure-templates'
             'build'
           ]

-    tests            :
-      app            :
-        options      :
-          depsPath   : '<%= deps.all.options.outputFile %>'
-          prefix     : '<%= deps.all.options.prefix %>'
-        src          : 'build/js/**/*_test.js'
+    tests                :
+      app                :
+        options          :
+          depsPath       : '<%= deps.all.options.outputFile %>'
+          prefix         : '<%= deps.all.options.prefix %>'
+        src              : 'build/js/**/*_test.js'

-    karma            :
-      unit           :
-        configFile   : 'karma.conf.js'
-
-    "http-server"        :
-      debug              :
-        root             : './public/debug/'
-        host             : '127.0.0.1'
-        port             : 1111
-        runInBackground  : yes
-      compiled           :
-        root             : './public/compiled/'
-        host             : '127.0.0.1'
-        port             : 2222
-
-    watch            :
-      options            :
-        livereload       : yes
-      configFiles    :
-        files        : [ 'Gruntfile.coffee', 'karma.conf.js' ]
-        options      :
-          reload     : yes
-      html               :
-        files            : [ '*.html' ]
-      src            :
-        files        : [ '**/*.coffee' ]
-        tasks        : [ 'clean', 'mkdir', 'coffee', 'coffee2closure', 'deps', 'karma' ]
-      styl           :
-        files        : [ '*.styl' ]
-        tasks        : [ 'stylus' ]
+    karma                :
+      unit               :
+        configFile       : 'karma.conf.js'

     builder              :
       all                :
@@ -147,6 +120,34 @@
           '--jscomp_error=visibility'
         ]

+    "http-server"        :
+      debug              :
+        root             : './public/debug/'
+        host             : '127.0.0.1'
+        port             : 1111
+        runInBackground  : yes
+      compiled           :
+        root             : './public/compiled/'
+        host             : '127.0.0.1'
+        port             : 2222
+
+    watch                :
+      options            :
+        livereload       : yes
+      configFiles        :
+        files            : [ 'Gruntfile.coffee', 'karma.conf.js' ]
+        options          :
+          reload         : yes
+      html               :
+        files            : [ '*.html' ]
+      src                :
+        files            : [ '**/*.coffee' ]
+        tasks            : [ 'clean', 'mkdir', 'coffee', 'coffee2closure', 'deps', 'karma' ]
+      styl               :
+        files            : [ '*.styl' ]
+        tasks            : [ 'stylus' ]
+
+
   grunt.loadNpmTasks 'grunt-contrib-clean'
   grunt.loadNpmTasks 'grunt-contrib-coffee'
   grunt.loadNpmTasks 'grunt-contrib-stylus'
@@ -156,6 +157,7 @@
   grunt.loadNpmTasks 'grunt-closure-coffee-stack'
   grunt.loadNpmTasks 'grunt-http-server'
   grunt.loadNpmTasks 'grunt-npm'
+

   grunt.registerTask 'build', 'Build stack.', (app = 'app') ->
     grunt.task.run [
@@ -171,6 +173,7 @@
       'http-server:compiled'
     ]

+
   grunt.registerTask 'default', 'Build stack.', (app = 'app') ->
     grunt.task.run [
       'clean'


mionr

mionr

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -94,7 +94,7 @@
         options:
           mode: 'gzip'
         expand: true
-        src: ['public/assets/*.min.*.*']
+        src: 'public/assets/*.min.*.*'
         dest: './'


payment: fix usage property of free plan subscription sample data

--- scripts/subscriptions/main.coffee
+++ scripts/subscriptions/main.coffee
@@ -24,7 +24,7 @@
     feeAmount  : 0
     quantities : quantities
     tags       : tags
-    usage      : []
+    usage      : {}

   (db.collection 'jPaymentSubscriptions').insert subscription, (err, [subscription])->
     return cb err if err


User-Importer: give enough time to bongo to handle all requests correctly

--- scripts/user-importer/main.coffee
+++ scripts/user-importer/main.coffee
@@ -104,7 +104,7 @@
         setTimeout ->
           console.log "\nALL DONE."
           process.exit 0
-        , 5000
+        , 10000

 csv = require 'csv'


Trying to extract doc comments

Trying to extract doc comments

--- quidoc.coffee
+++ quidoc.coffee
@@ -1,30 +1,163 @@
 ###
+Generate doc comments from CoffeeScript source files.
+###
+
 regexCommentedMembers = ///
-  (\n\x20\x20# .*)+     # Consecutive comment lines indented two spaces
-  \n\x20\x20(
-    [a-zA-Z0-9$][\w]+   # Class member identifier indented two spaces
-    :                   # Colon terminates identifier
-  )///
-###
+  (                     # First group captures the comment
+    (?:\n\x20\x20# .*)  # A comment line indented two spaces
+    +                   # Any number of comment lines
+  )
+  \n\x20\x20            # Two spaces at start of identifier line
+  (                     # Second group captures the identifier
+    [a-zA-Z0-9$][\w]+   # JavaScript member identifier
+  )
+  :                     # Colon terminates identifier
+  ///gm

 fs = require "fs"
 path = require "path"

-# Walk the tree whose root is the given path, listing all files. If a regex is
-# supplied, only names matching that expression are listed.
-ls = ( directory, regex ) ->
-  console?.log ""
-  console?.log directory + ":"
+# Walk the tree whose root is the given path, applying the given function to
+# each file. If a regex is supplied, only names matching that expression are
+# listed.
+walk = ( directory, regex, fn ) ->
   files = fs.readdirSync directory
   for file in files
-    match = regex is undefined or regex.test( file )
-    if match
-      console?.log file
     filePath = path.join directory, file
-    stats = fs.statSync filePath
-    if stats.isDirectory()
-      ls filePath
+    fn filePath if regex is undefined or regex.test( file )
+    walk filePath if fs.statSync( filePath ).isDirectory()

+
+docComments = ( source ) ->
+  console?.log source
+  comments = {}
+  match = regexCommentedMembers.exec source
+  while match != null
+    [ full, memberComment, memberName ] = match
+    comments[ memberName ] = memberComment
+    match = regexCommentedMembers.exec source
+  comments
+
+
+###
 args = process.argv.splice 2 # Ignore "node" and script name args
 root = if args[0]? then path.resolve args[0] else process.cwd()
-ls root, /\.coffee$/
+walk root, /\.coffee$/, ( filePath ) ->
+  comments = docComments filePath
+  console?.log comments
+###
+
+source = """
+###
+Lets user navigate content by moving left (backward) and right (forward).
+###
+
+class window.LateralNavigator extends Control
+
+  inherited:
+    content:
+      control: HorizontalPanels
+      ref: "panels"
+      content:
+        html: "div"
+        ref: "LateralNavigator_content"
+      leftClass: "VerticalAlign"
+      left:
+        control: BasicButton
+        ref: "LateralNavigator_previousButton"
+        class: "flat navigatorButton quiet"
+        content: "◀"
+      rightClass: "VerticalAlign"
+      right:
+        control: BasicButton
+        ref: "LateralNavigator_nextButton"
+        class: "navigatorButton quiet"
+        content: "▶"
+      tabindex: -1 # To get keyboard events
+    generic: true
+
+  # True if it's possible to navigate forward.
+  # The default implementation always returns true. Subclasses can override this
+  # to provide custom logic.
+  canGoNext: -> true
+
+  # True if it's possible to navigate backward.
+  # The default implementation always returns true. Subclasses can override this
+  # to provide custom logic.
+  canGoPrevious: -> true
+
+  # The content for the current position in the sequence.
+  content: Control.chain( "$LateralNavigator_content", "content", ->
+    @_updateButtons()
+  )
+
+  # The control class used to render the content.
+  contentClass: Control.property.class ( contentClass ) ->
+    $new = @$LateralNavigator_content().transmute contentClass, true
+    @referencedElement "LateralNavigator_content", $new
+
+  initialize: ->
+    @$LateralNavigator_previousButton().click => @_previousClick()
+    @$LateralNavigator_nextButton().click => @_nextClick()
+    @on
+      keydown: ( event ) =>
+        switch event.which
+          when 37 # Left
+            if !@$LateralNavigator_previousButton().disabled()
+              @_previousClick()
+          when 39 # Right
+            if !@$LateralNavigator_nextButton().disabled()
+              @_nextClick()
+      sizeChanged: =>
+        # HACK: Shouldn't need to directly reference HorizontalPanel elements.
+        this.$panels().$SimpleFlexBox_panel1().checkForSizeChange();
+        this.$panels().$SimpleFlexBox_panel2().checkForSizeChange();
+    @_updateButtons()
+
+  # Move forward.
+  # The default implementation does nothing.
+  next: ->
+
+  # The content of the "Next" button. Default is a right-pointing arrow.
+  nextButtonContent: Control.chain "$LateralNavigator_nextButton", "content"
+
+  # True if the Next button should be disabled. Default is false.
+  nextButtonDisabled: Control.chain "$LateralNavigator_nextButton", "disabled"
+
+  # Move backward.
+  # The default implementation does nothing.
+  previous: ->
+
+  # The content of the "Previous" button. Default is a left-pointing arrow.
+  previousButtonContent: Control.chain "$LateralNavigator_previousButton", "content"
+
+  # True if the Previous button should be disabled. Default is false.
+  previousButtonDisabled: Control.chain "$LateralNavigator_previousButton", "disabled"
+
+  _nextClick: ->
+    @next()
+    @_updateButtons()
+    @trigger "next"
+
+  _previousClick: ->
+    @previous()
+    @_updateButtons()
+    @trigger "previous"
+
+  _updateButtons: ->
+    @nextButtonDisabled !@canGoNext()
+    @previousButtonDisabled !@canGoPrevious()
+"""
+
+source2 = fs.readFileSync "c:/Source/quickui-catalog/coffee/LateralNavigator.coffee", "utf8"
+
+#console?.log docComments source2
+
+#regex = /((?:\n\x20\x20# .*)+)\n\x20\x20([a-zA-Z0-9$][\w]+):/gm
+regex = /((\n\x20\x20# .*)+)/gm
+match = regex.exec source2
+while match != null
+  [ full, capture ] = match
+  console.log capture
+  console.log ""
+  match = regex.exec source2


JAccount: Cleanup dummy admins

JAccount: Cleanup dummy admins

--- workers/social/lib/social/models/account.coffee
+++ workers/social/lib/social/models/account.coffee
@@ -605,9 +605,8 @@
     , (err, count)=>
       @update ($set: 'counts.topics': count), ->

-  dummyAdmins = [ "sinan", "devrim", "gokmen", "chris", "neelance",
-                  "fatihacet", "sent-hil", "kiwigeraint", "cihangirsavas",
-                  "fkadev", "arslan", "leventyalcin" ]
+  dummyAdmins = [ "sinan", "devrim", "gokmen", "chris", "fatihacet", "arslan",
+                  "sent-hil", "kiwigeraint", "cihangirsavas", "leventyalcin" ]

   userIsExempt: (callback)->
     console.log @isExempt, this


Added samet to dummyAdmins

Added samet to dummyAdmins

--- workers/social/lib/social/models/account.coffee
+++ workers/social/lib/social/models/account.coffee
@@ -663,7 +663,8 @@
       @update ($set: 'counts.topics': count), ->

   dummyAdmins = [ "sinan", "devrim", "gokmen", "chris", "fatihacet", "arslan",
-                  "sent-hil", "kiwigeraint", "cihangirsavas", "leventyalcin" ]
+                  "sent-hil", "kiwigeraint", "cihangirsavas", "leventyalcin",
+                  "samet" ]

   userIsExempt: (callback)->
     # console.log @isExempt, this


Add Levent Yalcin to dummy admins

Add Levent Yalcin to dummy admins

--- workers/social/lib/social/models/account.coffee
+++ workers/social/lib/social/models/account.coffee
@@ -711,8 +711,7 @@

   dummyAdmins = [ "sinan", "devrim", "gokmen", "chris", "neelance",
                   "fatihacet", "sent-hil", "kiwigeraint", "cihangirsavas",
-                  "fkadev", "arslan" ]
-
+                  "fkadev", "arslan", "leventyalcin" ]

   userIsExempt: (callback)->
     console.log @isExempt, this


iphone native config

iphone native config

--- app/config.coffee
+++ app/config.coffee
@@ -24,6 +24,14 @@
     oauthEndpoint: 'http://www.boorgle.com/oauth/'
     oauthRedirectUri: 'boorgle:///'

+#  # iPhone Native local
+#  Config =
+#    env: 'ios'
+#    host: 'http://localhost:3000/api/v1'
+#    clientId: 'boorgle-iphone'
+#    oauthEndpoint: 'http://localhost:3000/oauth/'
+#    oauthRedirectUri: 'boorgle:///'
+
 else
   # Production
   Config =


Update: AppCtrl add goBack function

Update: AppCtrl add goBack function

--- app/js/App.coffee
+++ app/js/App.coffee
@@ -11,7 +11,8 @@
   '$scope'
   '$rootScope'
   '$ionicModal'
-  ($scope, $rootScope, $ionicModal) ->
+  '$ionicNavBarDelegate'
+  ($scope, $rootScope, $ionicModal, $ionicNavBarDelegate) ->
     $ionicModal.fromTemplateUrl(
       'filterModal.html'
       ($ionicModal) ->
@@ -40,6 +41,8 @@
       scope: $scope
       animation: 'slide-in-up'
     )
+    $scope.goBack = ()->
+      $ionicNavBarDelegate.back()
 ])

 .directive('ngMultiSelect', ()->


Move the poller into the lib and mix it with the other classmixer stuffs. Update the test.

--- dashboard_spec.coffee
+++ dashboard_spec.coffee
@@ -1,10 +1,10 @@
-#= require dashboard
+#= require lib/dashboard_poller
 #= require mock-ajax

 describe "Dashboard - getData()", ->
   beforeEach ->
     jasmine.Ajax.useMock()
-    @dashboard = Dashboard
+    @dashboard = ttm.lib.DashboardPoller.build()

   describe "when the report is ready on the first iteration", ->
     it "should return the dashboard data", ->


handle url hashes

handle url hashes

Former-commit-id: a4b49455dbb81570094006ca9cb89b4bb27f80d0 [formerly d305661890646be3c42a62d9eaf25100233a90d0] [formerly b8109d7f4504276c1796e5fe2fa736dc6ae751a2 [formerly 2490f7dceb4e6e8cb7ba881932a0da31c0c724d8]] [formerly 634febc22d353ecebc18d14b3aa0ef13178ed53e [formerly 2cd98f4bd5ccd717a998748e97fe2d824a3ed21d] [formerly 914a8368e610f494b48a661377f70751088e728a [formerly 914a8368e610f494b48a661377f70751088e728a [formerly d76ec5f5c114a1f3441af2458bbc0a0e7efb601a]]]]
Former-commit-id: 94fa9f864f0459a85ce79f39286393aa66284dc1 [formerly f4300125ba58ef2759b8297294c41caa3b89fb60] [formerly 237a80b4c2d3b61ca645897dbb910d1d4ce53ea4 [formerly 7b7a389cd98ebbe3c9b5ff2a5f8381e94b26eb0f]]
Former-commit-id: b01695f1da3e7eb8f9f3a766435b84322b844361 [formerly 554ee69482672b4b59f401bfa76ece33742dc37d]
Former-commit-id: 2191ff95dd2ec99f8136f7059b535463720f0bda
Former-commit-id: 191cadf71795103628e88efb39b4b1eb9f1e524e

--- @client/browser_location.coffee
+++ @client/browser_location.coffee
@@ -35,7 +35,22 @@
       if query_param.length == 2
         loc.query_params[query_param[0]] = query_param[1]

+  # ...and parse anchors
+  hash = ''
+  if url.indexOf('#') > -1
+    [url, hash] = url.split('#')
+    url = '/' if url == ''
+
+    # When loading a page with a hash, we need to scroll the page
+    # to proper element represented by that id. This is hard to
+    # represent in Statebus, as it is more of an event than state.
+    # We'll set seek_to_hash here, then it will get set to null
+    # after it is processed.
+    loc.seek_to_hash = true
+
   loc.url = url
+  loc.hash = hash
+
   save loc

 ######
@@ -111,6 +126,20 @@

     SPAN null

+  componentDidUpdate : ->
+
+    loc = fetch 'location'
+    if loc.seek_to_hash
+      loc.seek_to_hash = false
+      save loc
+
+      # TODO: This doesn't work right now on initial page load
+      #       in Chrome & Safari for a return visitor. The
+      #       browser's remember scroll gets imposed after this
+      #       runs, and overrides it.
+      el = document.querySelector("##{loc.hash}")
+      el.scrollIntoView() if el
+
 relativeURLFromLocation = ->
   # location.search returns query parameters
   "#{location.pathname}#{location.search}#{location.hash}"
@@ -122,6 +151,8 @@
   if _.keys(loc.query_params).length > 0
     query_params = ("#{k}=#{v}" for own k,v of loc.query_params)
     relative_url += "?#{query_params.join('&')}"
+  if loc.hash?.length > 0
+    relative_url += "##{loc.hash}"
   relative_url


Update preserveMeteorDebug setting

Update preserveMeteorDebug setting

--- error_logger_client.coffee
+++ error_logger_client.coffee
@@ -19,26 +19,27 @@
         settings.requestSentTime = Date.now()
     )

-    _originalMeteorDebug = Meteor._debug
-    Meteor._debug = (message, stack) ->
-      if message instanceof Error
-        stack = message.stack
-        message = message.message
-      else if (_.isString(message) or message) and _.isUndefined(stack)
-        stack = _getStackFromMessage(message)
-        message = _firstLine(message)
+    unless Meteor.settings?.public?.preserveMeteorDebug
+      _originalMeteorDebug = Meteor._debug
+      Meteor._debug = (message, stack) ->
+        if message instanceof Error
+          stack = message.stack
+          message = message.message
+        else if (_.isString(message) or message) and _.isUndefined(stack)
+          stack = _getStackFromMessage(message)
+          message = _firstLine(message)

-      log =
-        errorType: 'METEOR'
-        browser: self.getBrowserData()
-        location: location.href
-        details:
-          message: message
-          stack: stack
-      self._postLog(log, (err, resp) ->
-        console.log if err then err else "METEOR_LOG_OK"
-      )
-      _originalMeteorDebug.apply(this, arguments)
+        log =
+          errorType: 'METEOR'
+          browser: self.getBrowserData()
+          location: location.href
+          details:
+            message: message
+            stack: stack
+        self._postLog(log, (err, resp) ->
+          console.log if err then err else "METEOR_LOG_OK"
+        )
+        _originalMeteorDebug.apply(this, arguments)

     window.onerror = (message, file, line, column, error) ->
       # Ignore if msg is the following


remove debugging stmt

remove debugging stmt

--- spec/lanes/models/BaseSpec.coffee
+++ spec/lanes/models/BaseSpec.coffee
@@ -100,7 +100,6 @@
         Lanes.Models.Base.extend(Base)
         class Model
             constructor: -> super
-        debugger
         Model = Base.extend(Model)
         expect(Model.Collection::model).toEqual(Model)


fixed minor bug

fixed minor bug

--- dao/VoteDAO._coffee
+++ dao/VoteDAO._coffee
@@ -19,7 +19,7 @@
   update: (id, newData, _) ->
     connection = Connection.find(id, _)
     connection.update(newData, _)
-  return connection
+    return connection

   delete: (id, _) ->
     connection = Connection.find(id, _)


rtmp: Fix the handling of RTMPT session timeout

--- rtmp.coffee
+++ rtmp.coffee
@@ -1665,7 +1665,7 @@
         return
       if not @timeoutTimer?
         return
-      if Date.now() - @lastTimeoutScheduledTime < SESSION_TIMEOUT
+      if Date.now() - @lastTimeoutScheduledTime < RTMPT_SESSION_TIMEOUT
         return
       console.log "RTMPT session timeout: #{@id}"
       @close()


refactor

refactor

--- lib/codeglance-view.coffee
+++ lib/codeglance-view.coffee
@@ -24,18 +24,16 @@
     @editor.getLineHeightInPixels()

   resetGrammar: ->
-    grammar = switch atom.config.get 'minimap-codeglance.highlightCode'
+    @editor.setGrammar switch atom.config.get 'minimap-codeglance.highlightCode'
       when true then @minimap.getTextEditor().getGrammar()
       when false then atom.grammars.grammarForScopeName 'text.plain.null-grammar'
-    if grammar isnt @editor.getGrammar()
-      @editor.setGrammar grammar

   resetText: ->
     @editor.setText @minimap.getTextEditor().getText()

   show: (parentTextEditor) ->
     # hide the border until content is visible
-    @style.borderColor = if @clientHeight is 0 then'transparent' else ''
+    @style.borderColor = if @clientHeight is 0 then 'transparent' else ''
     @style.display = ''

   hide: ->
@@ -62,44 +60,44 @@
     @resetGrammar()
     @resetText()

-  showLinesAtOffset: (offset) ->
+  showLinesAtOffset: (offsetInPixels) ->
     @resize() if @clientHeight is 0
-    offsetInLines = @pixelsToLines offset
-    cursorLine = @getCursorLine offsetInLines
-    return @hide() unless cursorLine?
-    @scrollToLine cursorLine
-    @alignWithCursor offset
+    offsetInRows = @pixelsToRows offsetInPixels
+    sourceScreenRow = @sourceScreenRowForOffset offsetInRows
+    ownScreenRow = @ownScreenRowForSourceScreenRow sourceScreenRow
+    @scrollToScreenRow ownScreenRow
+    @alignWithCursor offsetInPixels

-  pixelsToLines: (px) ->
+  pixelsToRows: (px) ->
     lineHeight = @minimap.charHeight + @minimap.interline
     Math.floor px / lineHeight

-  getCursorLine: (offsetInLines) ->
-    firstVisibleLine = @minimap.getFirstVisibleScreenRow()
-    cursorLine = firstVisibleLine + offsetInLines
-    return if cursorLine > @minimap.getTextEditor().getLastScreenRow()
-    cursorLine = @minimap.getTextEditor().bufferPositionForScreenPosition([cursorLine, 0]).row
-    @editor.screenPositionForBufferPosition([cursorLine, 0]).row
+  sourceScreenRowForOffset: (offsetInRows) ->
+    firstVisibleScreenRow = @minimap.getFirstVisibleScreenRow()
+    sourceScreenRow = firstVisibleScreenRow + offsetInRows

-  scrollToLine: (line) ->
-    nLines = atom.config.get 'minimap-codeglance.numberOfLines'
-    firstLine = Math.max 0, line - Math.floor nLines / 2
+  ownScreenRowForSourceScreenRow: (sourceScreenRow) ->
+    return -1 if sourceScreenRow > @minimap.getTextEditor().getLastScreenRow()
+    bufferRow = @minimap.getTextEditor().bufferPositionForScreenPosition([sourceScreenRow, 0]).row
+    @editor.screenPositionForBufferPosition([bufferRow, 0]).row
+
+  scrollToScreenRow: (screenRow) ->
+    return @hide() if screenRow is -1
+    @editor.setCursorScreenPosition [screenRow, 0]
     @show()
-    @editor.setCursorScreenPosition [line, 0]
-    @editor.displayBuffer.setScrollTop firstLine * @getLineHeight()

-  alignWithCursor: (offset) ->
+  alignWithCursor: (cursorOffsetInPixels) ->
     return if @position isnt 'cursor'
-    translateY = offset - @clientHeight / 2
-    translateY = Math.max @getMinTranslateY(), translateY
-    translateY = Math.min @getMaxTranslateY(), translateY
+    offsetInPixels = cursorOffsetInPixels - @clientHeight / 2
+    offsetInPixels = Math.max @getMinOffsetY(), offsetInPixels
+    offsetInPixels = Math.min @getMaxOffsetY(), offsetInPixels
     requestAnimationFrame =>
-      @style.transform = "translateY(#{translateY}px)"
+      @style.transform = "translateY(#{offsetInPixels}px)"

-  getMinTranslateY: ->
+  getMinOffsetY: ->
     -parseInt getComputedStyle(this).borderTopWidth

-  getMaxTranslateY: ->
+  getMaxOffsetY: ->
     borderBottom = parseInt getComputedStyle(this).borderBottomWidth
     @parentNode.host.clientHeight - @clientHeight + borderBottom


change path for noty plus

change path for noty plus

--- router.coffee
+++ router.coffee
@@ -9,7 +9,7 @@
 defaultPort = 3000
 # Routes for redirection depending on given path
 routes =
-    "/noty-plus": 8001
+    "/apps/noty-plus": 8001

 # Return port corresponding to given path, returns defaultPort if no


Take out 'dataNotFound' built-in hook

Take out 'dataNotFound' built-in hook

--- router.coffee
+++ router.coffee
@@ -1,6 +1,4 @@
 Router.onBeforeAction 'loading'
-Router.onBeforeAction 'dataNotFound'
-
 Router.map ->

   #


Added static to the watch tasks

Added static to the watch tasks

--- .metalsmith/gulpfile.coffee
+++ .metalsmith/gulpfile.coffee
@@ -54,7 +54,7 @@
 #
 # Watch the metalsmith code and reload it when changes are detected.
 # Note that this will not reload changes to this Gulpfile.
-gulp.task 'watch:code', -> gulp.watch paths.code, ->
+gulp.task 'watch:code', -> gulp.watch paths.code, ['static'], ->
   util.log 'Code changed, reloading and compiling.'
   delete require.cache[path.join __dirname, 'metal.coffee']
   metal = require './metal'


Remove behavior from bbaseline game

Remove behavior from bbaseline game

--- src/load/baseline.coffee
+++ src/load/baseline.coffee
@@ -26,7 +26,7 @@
           shape: 'turtle'
           position: [0,0]
           color: 'limegreen'
-          behavior: {first: [], repeat: ['forward']}
+          actions: {first: [], repeat: ['forward']}
           editable: true
         }
       ]


port update

port update

--- server.coffee
+++ server.coffee
@@ -131,7 +131,7 @@
 # Express config
 app.configure ->
   app.use express.favicon(__dirname + "/resources/public/img/jinteki.ico")
-  app.set 'port', process.env.OPENSHIFT_NODEJS_PORT || 3000
+  app.set 'port', process.env.OPENSHIFT_NODEJS_PORT || 1045
   app.set 'ipaddr', process.env.OPENSHIFT_NODEJS_IP || "0.0.0.0"
   app.use express.methodOverride() # provide PUT DELETE
   app.use express.cookieParser()


Gardening

Gardening

--- server.coffee
+++ server.coffee
@@ -12,6 +12,7 @@
   debug = require('debug') 'shrub:server'
   debugSilly = require('debug') 'shrub-silly:server'

+  config = require 'config'
   errors = require 'errors'
   middleware = require 'middleware'
   pkgman = require 'pkgman'
@@ -28,7 +29,6 @@
   # Load the configuration.
   debug 'Loading config...'

-  config = require 'config'
   config.load()
   config.loadPackageSettings()

@@ -46,11 +46,6 @@
     'shrub-core:bootstrapMiddleware'
   )

-  middleware.fromHook(
-    'shrubCoreBootstrapMiddleware'
-    config.get 'packageSettings:shrub-core:shrubCoreBootstrapMiddleware'
-  )
-
   debugSilly 'Bootstrap middleware loaded.'

   # Dispatch the bootstrap middleware stack and log if everything is okay.


Remove extra '-' in text/plain response

Remove extra '-' in text/plain response

--- server.coffee
+++ server.coffee
@@ -24,7 +24,7 @@
 dooutput = (res, message, subtitle) ->
   res.format
     "text/plain": ->
-      res.send "#{message} - #{subtitle}"
+      res.send "#{message} #{subtitle}"
     "application/json": ->
       res.send JSON.stringify { message: message, subtitle: subtitle }
     "text/html": ->


Allow fetching basic profile without first creating a model instance

--- lib/assets/javascripts/models/basic_profile.js.coffee
+++ lib/assets/javascripts/models/basic_profile.js.coffee
@@ -6,38 +6,42 @@

   @content_fields = ['name', 'bio', 'location', 'gender', 'birthdate', 'website_url']

+  @fetch: (params = {}, options = {}) ->
+    entity = params.entity || options.model?.get('entity')
+
+    if not(entity)
+      throw new Error("#{@name}.fetch requires an entity!")
+
+    success = (model, xhr) =>
+      options.success?(model, xhr)
+      model.trigger('fetch:success', model, xhr)
+      @trigger('fetch:success', model, xhr)
+    failure = (model, res, xhr) =>
+      options.failure?(model, res, xhr)
+      model?.trigger('fetch:failure', model, res, xhr)
+      @trigger('fetch:failure', model, res, xhr)
+
+    TentStatus.tent_client.post.list(
+      params:
+        entity: entity
+        types: [@post_type.toString()]
+        limit: 1
+      callback: (feed, xhr) =>
+        return failure(options.model, feed, xhr) unless xhr.status in [200...300]
+        posts = feed.data
+        return failure(options.model, feed, xhr) unless posts.length && post = _.find(posts, (item) =>
+          (new TentClient.PostType(item.type)).base == @post_type.base
+        )
+        model = new @(post)
+        success(model, xhr)
+    )
+
   parseAttributes: =>
     super
     @attachmentsUpdated(@get('attachments'))

   fetch: (params = {}, options = {}) =>
-    xhr = null
-    entity = params.entity || @get('entity')
-
-    if not(entity)
-      throw new Error("#{@constructor.name}.prototype.fetch requires an entity!")
-
-    success = =>
-      options.success?(@, xhr)
-      @trigger('fetch:success', @, xhr)
-    failure = =>
-      options.failure?(@, xhr)
-      @trigger('fetch:failure', @, xhr)
-
-    TentStatus.tent_client.post.list(
-      params:
-        entity: entity
-        types: [@constructor.post_type.toString()]
-        limit: 1
-      callback: (feed, xhr) =>
-        return failure() unless xhr.status in [200...300]
-        posts = feed.data
-        return failure() unless posts.length && post = _.find(posts, (item) =>
-          (new TentClient.PostType(item.type)).base == @constructor.post_type.base
-        )
-        @parseAttributes(post)
-        success()
-    )
+    @constructor.fetch(params, _.extend(model: @, options))

   attachmentsUpdated: (value) =>
     setDefaultAvatar = =>


Mesh: Workaround for bug #14

Mesh: Workaround for bug #14

--- engine/mesh.coffee
+++ engine/mesh.coffee
@@ -392,7 +392,7 @@
             for i in [0...num_values]
                 cuv.push null
         return true
-
+
     # min_length_px is the minimum length of the average polygon, in screen pixels
     get_lod_mesh: (viewport, min_length_px) ->
         amesh = @
@@ -437,11 +437,14 @@
             for lod in @lod_objects by -1
                 ob = lod.object
                 visual_size_px = ob.avg_poly_length * poly_length_to_visual_size
-                if ob.avg_poly_length > biggest_length and visual_size_px < min_length_px and ob.data?
+                if ob.avg_poly_length > biggest_length and visual_size_px < min_length_px and ob.data?.attrib_pointers
                     biggest_length = ob.avg_poly_length
                     @last_lod_object = amesh = ob

+            # NOTE TODO: Fix when lod levels can't be seen if the main level is not configured
+            if amesh != @ and @data? and @materials.length == 0
+                @configure_materials()
+
         return amesh

 module.exports = {Mesh}
-


Hack for now to use existing git index model in hunk

--- lib/patch/hunk-view.coffee
+++ lib/patch/hunk-view.coffee
@@ -24,8 +24,6 @@

   attachedCallback: ->
     @base = @el.closest('.git-root-view')
-
-    @git = new GitIndex

   createLineNode: ->
     lineNode = document.createElement('div')
@@ -57,7 +55,7 @@

       contentNode.innerHTML = highlighted if highlighted

-  setHunk: (@patch, @index, @status) ->
+  setHunk: (@patch, @index, @status, @git) ->
     @hunk = @patch.hunks()[@index]
     header = @hunk.header()
     headerNode = @createLineNode()
@@ -211,8 +209,8 @@
     else
       @git.unstagePatch(patch, @patch)

-    promise.then ->
-      atom.emit('did-update-git-repository')
+    promise.then =>
+      @git.emit('did-update-repository')

 module.exports = document.registerElement 'git-hunk-view',
   prototype: HunkView.prototype


Write symfile to disk on save

Write symfile to disk on save

--- src/model/symfile.coffee
+++ src/model/symfile.coffee
@@ -4,22 +4,34 @@
 fs = require 'fs-promise'

 DIST_DIR = 'pool/symbols'
+COMPOSITE_INDEX = 'compositeIndex'

 Symfile = sequelize.define('symfiles', {
   id:
     type: Sequelize.INTEGER
     autoIncrement: yes
     primaryKey: yes
-  os: Sequelize.STRING
-  code: Sequelize.STRING
-  arch: Sequelize.STRING
+  os:
+    type: Sequelize.STRING
+    unique: COMPOSITE_INDEX
+  name:
+    type: Sequelize.STRING
+    unique: COMPOSITE_INDEX
+  code:
+    type: Sequelize.STRING
+    unique: COMPOSITE_INDEX
+  arch:
+    type: Sequelize.STRING
+    unique: COMPOSITE_INDEX
   contents: Sequelize.TEXT
 })

-Symfile.sync(force: yes)
+Symfile.sync()

-Symfile.saveToDisk = (symfile, callback) ->
-  console.log('todo')
+Symfile.saveToDisk = (symfile) ->
+  symfileDir = "#{DIST_DIR}/#{symfile.name}/#{symfile.code}"
+  fs.mkdirs(symfileDir).then ->
+    fs.writeFile("#{symfileDir}/#{symfile.name}.sym", symfile.contents)

 Symfile.createFromRequest = (req, callback) ->
   form = new formidable.IncomingForm()
@@ -36,9 +48,27 @@
         if dec != 'MODULE'
           throw new Error 'Could not parse header (expecting MODULE as first line)'

-        Symfile.create({ os: os, arch: arch, code: code, name: name , contents: contents})
-          .then (symfile) ->
-            callback(null, symfile)
+        props =
+          os: os
+          arch: arch
+          code: code
+          name: name
+          contents: contents
+
+        sequelize.transaction (t) ->
+          whereDuplicated =
+            where: { os: os, arch: arch, code: code, name: name}
+
+          Symfile.findOne(whereDuplicated, {transaction: t}).then (duplicate) ->
+            p =
+              if duplicate?
+                duplicate.destroy({transaction: t})
+              else
+                Promise.resolve()
+            p.then ->
+              Symfile.create(props, {transaction: t}).then (symfile) ->
+                Symfile.saveToDisk(symfile).then ->
+                  callback(null, symfile)

       .catch (err) ->
         callback err


realtimecontroller: when a user requests to unsubscribe from a channel, unsubscribe them from all the connected browsers

--- client/Main/realtimecontroller.coffee
+++ client/Main/realtimecontroller.coffee
@@ -40,6 +40,9 @@

       return callback err  if err

+      # when we make an authentication request, server responses with realtimeToken
+      # in cookie here. If it is not set, then there is no need to subscription attempt
+      # to pubnub
       realtimeToken = Cookies.get("realtimeToken")

       return callback { message : 'Could not find realtime token'}  unless realtimeToken
@@ -99,6 +102,9 @@

   unsubscribePubnub: (channel) ->
+
+    return  unless channel
+
     {token} = channel
     channelName = "channel-#{token}"
     @pubnub.unsubscribe({
@@ -159,6 +165,11 @@
         message : (message, env, channel) =>
           return  unless message
           {eventName, body} = message
+          # when a user is connected in two browsers, and leaves a channel, in second one
+          # they receive RemovedFromChannel event for their own. Therefore we must unsubscribe
+          # user from all connected devices.
+          if eventName is 'RemovedFromChannel' and body.accountId is KD.whoami().socialApiId
+            return @unsubscribePubnub message.channel

           # no need to emit any events when not subscribed
           return  unless @channels[channel]


shortcuts: use lodash#debounce instead of lodash#throttle :honeybee:

--- client/app/lib/shortcuts/index.coffee
+++ client/app/lib/shortcuts/index.coffee
@@ -10,7 +10,7 @@

 STORAGE_NAME    = 'shortcuts'
 STORAGE_VERSION = '7'
-THROTTLE_WAIT   = 300
+DEBOUNCE_WAIT   = 300

 module.exports =

@@ -28,7 +28,6 @@
   # instance, and persists the state of a keyconfig#Collection to the app storage.
   #
   constructor: (options={}, data) ->
-

     @_store  = null
     @_buffer = null
@@ -84,10 +83,7 @@

   # Persists changes to app storage.
   #
-  # This is a throttled method and will only be called once per every
-  # _THROTTLE_WAIT_ milliseconds.
-  #
-  _save: _.throttle ->
+  _save: _.debounce ->

     unless @_store.isReady
       console.warn 'could not persist shortcut changes'
@@ -120,9 +116,7 @@

     return

-  , THROTTLE_WAIT,
-    leading  : no
-    trailing : yes
+  , DEBOUNCE_WAIT, no # see https://lodash.com/docs#debounce

   # Buffers up changed models.


shortcuts: fix major bug found in shortcuts change listener that messes up save queue :shit:

--- client/app/lib/shortcuts/index.coffee
+++ client/app/lib/shortcuts/index.coffee
@@ -129,7 +129,6 @@
   _handleShortcutsChange: (collection, model) ->

     queue   = @_buffer[collection.name]
-    idx     = _.findWhere queue, name: model.name
     obj     = name: model.name
     binding = klass._getPlatformBinding model

@@ -142,7 +141,10 @@
     # appstorage. defaults may change, but user overrides should stay.
     obj.enabled = if model.options?.enabled is no then no else yes

-    queue[((~idx and idx) or queue.length)] = obj
+    idx = _.findIndex queue, name: model.name
+    idx = if ~idx then idx else queue.length
+
+    queue[idx] = obj

     @_save()


Improved: code style

Improved: code style

--- client/app/views/calendar_view.coffee
+++ client/app/views/calendar_view.coffee
@@ -151,7 +151,7 @@
                 @popover = null
                 return

-        @popover = if options.type is 'event' then new EventPopover options
+        @popover = new EventPopover options
         @popover.render()

     onChangeView: (view) =>


ignore method redefinition warning

ignore method redefinition warning

--- lib/runtime/console.coffee
+++ lib/runtime/console.coffee
@@ -31,8 +31,8 @@

     client.handle 'input', => @input()

-    client.onStdout (s) => @c.stdout s
-    client.onStderr (s) => @c.stderr s
+    client.onStdout (s) => @stdout s
+    client.onStderr (s) => @stderr s

   deactivate: ->
     @subs.dispose()
@@ -49,6 +49,17 @@
     atom.views.getView(@c).classList.add 'julia'
     history.read().then (entries) =>
       @c.history.set entries
+
+  ignored: ['WARNING: Method definition require(Symbol)']
+  ignore: (s) ->
+    for i in @ignored
+      return true if s.startsWith(i)
+
+  stdout: (data) -> @c.stdout data
+
+  stderr: (data) ->
+    data = data.split('\n').filter((x)=>!@ignore x).join("\n")
+    if data then @c.stderr data

   open: ->
     # Seems like atom should be doing this check for us,


removed animation from popover

removed animation from popover

--- app/assets/javascripts/pt/tags/popover.js.coffee
+++ app/assets/javascripts/pt/tags/popover.js.coffee
@@ -19,6 +19,7 @@
           #if not a url assume it's content
           if url.charAt(0)!="/"
             $el.popover
+              animation: false
               content: url
               html: true
               trigger: 'manual'
@@ -31,6 +32,7 @@
               url: url
               success: (html) ->
                 $el.popover
+                  animation: false
                   content: html
                   html: true
                   trigger: 'manual'


Restore "r" shortcut

Restore "r" shortcut

--- app/assets/javascripts/shortcuts_issuable.coffee
+++ app/assets/javascripts/shortcuts_issuable.coffee
@@ -6,6 +6,10 @@
     super()
     Mousetrap.bind('a', @openSidebarDropdown.bind(@, 'assignee'))
     Mousetrap.bind('m', @openSidebarDropdown.bind(@, 'milestone'))
+    Mousetrap.bind('r', =>
+      @replyWithSelectedText()
+      return false
+    )
     Mousetrap.bind('j', =>
       @prevIssue()
       return false


Fix markup

Fix markup

--- app/assets/javascripts/views/user_view.js.coffee
+++ app/assets/javascripts/views/user_view.js.coffee
@@ -157,7 +157,7 @@

     yield: ->
       @selector.append '

'
-      @selector.append '
'
+      @selector.append ''
       @selector.find('section').append @template(topic) for topic in @topics.topics
       @paginate @selector
       @update_title 'Topics'


[server] filter out countries with only 1 user over period of data; round up bDensity to reduce json size

--- server/ga.coffee
+++ server/ga.coffee
@@ -249,7 +249,7 @@

       # remove (not set) country
       current = current.filter (country) ->
-        country[0] != "(not set)"
+        country[0] != "(not set)" and +country[1] > 1

       result = current.map (d) ->
         name: d[0]
@@ -257,7 +257,9 @@
         bUsers: +d[1]

       result.forEach (country) ->
-        geoPromise = geo.getPop(country.isoCode).then (pop) -> country.bDensity = country.bUsers / pop * 1000000; return
+        geoPromise = geo.getPop(country.isoCode).then (pop) ->
+          country.bDensity = Math.ceil(country.bUsers / pop * 1000000)
+          return
         # get population from world bank api then calc bower user density per 1m pop
         geoPromises.push geoPromise
         return


Final fixes for Search

Final fixes for Search

--- modules/player/search.coffee
+++ modules/player/search.coffee
@@ -6,13 +6,15 @@
     @pending = {}

   doSearch: (msg, l, query)->
-    @pending[msg.id] = search = { msg, query, l, react: [] }
+    @pending[msg.id] = search = { msg, query, l }
     search.results = await @util.getInfo("ytsearch10:#{query}")
     if search.results.partial
       await @updateResults(msg.id)
       search.results.on('video', => @updateResults(msg.id))
+      search.results.on('done', => @updateResults(msg.id))
       r = await search.rmsg.awaitReactions (r, u) =>
         r.emoji.name in options and u.id is msg.author.id
+      , max: 1
       try await search.rmsg.delete()
       delete @pending[msg.id]
       video = search.results.items[options.indexOf(r.first().emoji.name)]
@@ -25,7 +27,7 @@

   updateResults: (id)->
     return unless @pending[id]
-    { l, results, rmsg, react } = @pending[id]
+    { l, results, rmsg } = @pending[id]
     embed =
       author:
         name: if results.partial then l.player.hud.searching else l.player.hud.results
@@ -35,9 +37,7 @@
       embed.description += "#{options[i]} [#{item.title.replace(/\]/, '\\]')}]"
       embed.description += "(#{item.webpage_url.replace(/\]/, '\\]')})"
       embed.description += " (#{@util.displayTime item.duration})\n"
-      if rmsg and not options[i] in react
-        await @pending[id].rmsg.react(options[i])
-        react.push(options[i])
+      if rmsg then try await rmsg.react(options[i])
     if rmsg then try
       await rmsg.edit('', { embed })
       return rmsg


not this model

not this model

--- apps/personalize/client/mixins/followable.coffee
+++ apps/personalize/client/mixins/followable.coffee
@@ -43,7 +43,7 @@
     analyticsHooks.trigger 'followable:followed',
       message: @analyticsFollowMessage
       modelName: displayModel
-      id: @model.get('id')
+      id: model.get('id')

   unfollow: (e) ->
     id = $(e.currentTarget).data 'id'
@@ -54,4 +54,4 @@
     analyticsHooks.trigger 'followable:followed',
       message: @analyticsUnfollowMessage
       modelName: displayModel
-      id: @model.get('id')
+      id: model.get('id')


Add Commands to set/unset context for janky

--- src/scripts/janky.coffee
+++ src/scripts/janky.coffee
@@ -141,6 +141,23 @@
       else
         msg.send "I couldn't update the room. Got HTTP status #{statusCode}"

+  robot.respond /ci set context ([-_0-9a-zA-Z\.]+) (.*)$/i, (msg) ->
+    repo = msg.match[1]
+    context = encodeURIComponent(msg.match[2])
+    put "#{repo}/context?context=#{context}", {}, (err, statusCode, body) ->
+      if [404, 403, 200].indexOf(statusCode) > -1
+        msg.send body
+      else
+        msg.send "I couldn't update the context. Got HTTP status #{statusCode}"
+
+  robot.respond /ci unset context ([-_0-9a-zA-Z\.]+)$/i, (msg) ->
+    repo = msg.match[1]
+    delete "#{repo}/context", {}, (err, statusCode, body) ->
+      if [404, 403, 200].indexOf(statusCode) > -1
+        msg.send body
+      else
+        msg.send "I couldn't update the context. Got HTTP status #{statusCode}"
+
   robot.respond /ci rooms$/i, (msg) ->
     get "rooms", { }, (err, statusCode, body) ->
       if statusCode == 200


small adjustment

small adjustment

--- src/server/logger.coffee
+++ src/server/logger.coffee
@@ -23,7 +23,7 @@
 			console.log `'\033c'`

 		catch e
-			# This adds newlines untill console has been cleared
+			# This adds newlines untill console has been cleared and goed back to top
 			console.log `'\u001b[2J\u001b[0;0H'`


Use port from env.

Use port from env.

--- src/server/server.coffee
+++ src/server/server.coffee
@@ -1,16 +1,10 @@
 Train = require "./lib/Train"
 path = require "path"
 express = require "express"
-nconf = require "nconf"

 root = path.join __dirname, "..", ".."

-nconf.argv()
-	.env()
-	.file
-		file: path.join root, 'server.json'
-	.defaults
-		port: 3000
+port = process.env.PORT || 3000

 train = new Train

@@ -44,7 +38,6 @@

 module.exports = do ->
 	serve: ->
-		port = nconf.get 'port'
 		server.listen port
 		console.log "Train Server listening on port #{port}"
 	stop: ->


add misc.server times.

add misc.server times.

--- src/smc-util/misc.coffee
+++ src/smc-util/misc.coffee
@@ -1283,8 +1283,34 @@
 exports.minutes_ago      = (m)  -> exports.seconds_ago(60*m)
 exports.hours_ago        = (h)  -> exports.minutes_ago(60*h)
 exports.days_ago         = (d)  -> exports.hours_ago(24*d)
-exports.weeks_ago        = (d)  -> exports.days_ago(7*d)
-exports.months_ago       = (d)  -> exports.days_ago(30.5*d)
+exports.weeks_ago        = (w)  -> exports.days_ago(7*w)
+exports.months_ago       = (m)  -> exports.days_ago(30.5*m)
+
+if localStorage?
+    # Versions of the above, but give the relevant point in time but
+    # on the *server*.  These are only available in the web browser.
+    exports.server_time             = ()   -> new Date(new Date() - (parseFloat(localStorage.clock_skew) ? 0))
+    exports.server_milliseconds_ago = (ms) -> new Date(new Date() - ms - (parseFloat(localStorage.clock_skew) ? 0))
+    exports.server_seconds_ago      = (s)  -> exports.server_milliseconds_ago(1000*s)
+    exports.server_minutes_ago      = (m)  -> exports.server_seconds_ago(60*m)
+    exports.server_hours_ago        = (h)  -> exports.server_minutes_ago(60*h)
+    exports.server_days_ago         = (d)  -> exports.server_hours_ago(24*d)
+    exports.server_weeks_ago        = (w)  -> exports.server_days_ago(7*w)
+    exports.server_months_ago       = (m)  -> exports.server_days_ago(30.5*m)
+else
+    # On the server, these functions are aliased to the functions above, since
+    # we assume that the server clocks are sufficiently accurate.  Providing
+    # these functions makes it simpler to write code that runs on both the
+    # frontend and the backend.
+    exports.server_time_ms          = -> new Date()
+    exports.server_milliseconds_ago = exports.milliseconds_ago
+    exports.server_seconds_ago      = exports.seconds_ago
+    exports.server_minutes_ago      = exports.minutes_ago
+    exports.server_hours_ago        = exports.hours_ago
+    exports.server_days_ago         = exports.days_ago
+    exports.server_weeks_ago        = exports.weeks_ago
+    exports.server_months_ago       = exports.months_ago
+

 # Specific easy to read and describe point in time before another point in time tm.
 # (The following work exactly as above if the second argument is excluded.)


Finish implementation

Finish implementation

--- src/smc-util/misc.coffee
+++ src/smc-util/misc.coffee
@@ -552,19 +552,17 @@
     # make email address lower case
     return email_address.toLowerCase()

-# Expects a comma or semicolon separated list of strings and/or email addresses
-# If an email address is included, only searces for the email address
-#
-# Accepts the following example terms
-#     Firstname lastname, Email@something.com; ... ("firstname lastname" will be included in string_queries)
-#     Firstname lastname Email@something.com, ... (Will ignore "firstname lastname")
-#     First Last <EmailAddress@email.com>, ...
-#     Firstname Lastname, ...
-#     <JustAnEmail@mail.com>; ...
-#
-# Will SILENTLY REJECT the following terms:
-#    <Email@noEndingBracket, ...
-#    Email@NoStartingBracket>, ...
+
+# Expects a comma or semicolon separated list of strings and/or email addresse
+#
+# Non-email strings are ones without an '@'
+#
+# Email strings may contain one or more space separated emails.
+# Emails may be wrapped by angle brackets.
+#   ie. <name@email.com> is valid and understood as name@email.com
+#   (Note that <<name@email.com> will be <name@email.com which is not valid)
+#
+# Emails must be legal as specified by RFC822
 #
 # returns an object with the queries in lowercase
 #    string_queries: ["firstname lastname"]
@@ -581,11 +579,15 @@
             else
                 # extract just the email address out
                 for a in exports.split(x)
+                    # Ensures that we don't throw away emails like
+                    # "<validEmail>"withquotes@mail.com
                     if a[0] == '<'
-                        a = re.exec(a)[1]
+                        match = email_re.exec(a)
+                        a = match?[1] ? a
                     if exports.is_valid_email_address(a)
                         r.email_queries.push(a)
     return r
+

 # Delete trailing whitespace in the string s.
 exports.delete_trailing_whitespace = (s) ->


make it possible to debug "Store has a cycle in its computed values" (https://github.com/sagemathinc/smc/issues/1267)

--- src/smc-util/misc.coffee
+++ src/smc-util/misc.coffee
@@ -1857,6 +1857,7 @@

     # Detect cycles
     if num_edges != 0
+        window?._DAG = DAG  # so it's possible to debug in browser
         throw new Error "Store has a cycle in its computed values"

     if omit_sources


去除多余斜杠

去除多余斜杠

--- lib/autocomplete/.coffee/provider.coffee
+++ lib/autocomplete/.coffee/provider.coffee
@@ -11,7 +11,7 @@
     suggestions = []

     if prefix.toLowerCase().includes('yyapi')
-      for suggestion in @getYYApiPackage().concat(@getApiEnt())\.concat(@getApiRes()).concat(@getApiUtils())
+      for suggestion in @getYYApiPackage().concat(@getApiEnt()).concat(@getApiRes()).concat(@getApiUtils())
         suggestion.replacementPrefix = prefix
         suggestion.descriptionMoreURL = 'http://dev.yypm.com/yylive/? \
         post=posts/yyscriptpluginsdk/api.md'


Removed unused array

Removed unused array

--- lib/pg-hoff-autocomplete-provider.coffee
+++ lib/pg-hoff-autocomplete-provider.coffee
@@ -18,8 +18,6 @@
     getSuggestions: (options) ->
         if not atom.config.get('pg-hoff.autocompletionEnabled')
             return []
-
-        suggestions = []

         text = atom.workspace.getActiveTextEditor().getText()
         before = options.editor.getTextInBufferRange([[0, 0], options.bufferPosition])


Template

Template

- Resurrect support for "ez-*" Template names in "ng".

--- src/base/Template/Template.coffee
+++ src/base/Template/Template.coffee
@@ -88,10 +88,7 @@
 					sel = "."+@_map_prefix+"-"+clean_k
 				else
 					prefix = toDash(@_name)
-					if CUI.__ng__
-						sel = ".cui-"+prefix+"-"+clean_k
-					else
-						sel = ".ez-"+prefix+"-"+clean_k+",.cui-"+prefix+"-"+clean_k
+					sel = ".ez-"+prefix+"-"+clean_k+",.cui-"+prefix+"-"+clean_k
 			else
 				sel = v


Fix bug causing Executable to use Docker first, instead of builtin command

--- src/beautifiers/executable.coffee
+++ src/beautifiers/executable.coffee
@@ -396,6 +396,7 @@
       })
     return @docker

+  installedWithDocker: false
   init: () ->
     super()
       .catch((error) =>
@@ -403,6 +404,7 @@
         @docker.init()
           .then(=> @runImage(@versionArgs, @versionRunOptions))
           .then((text) => @saveVersion(text))
+          .then(() => @installedWithDocker = true)
           .then(=> @)
           .catch((dockerError) =>
             @debug(dockerError)
@@ -411,7 +413,7 @@
       )

   run: (args, options = {}) ->
-    if @docker and @docker.isInstalled
+    if @installedWithDocker and @docker and @docker.isInstalled
       return @runImage(args, options)
     super(args, options)


change placement of pluging definition

change placement of pluging definition

--- vendor/assets/javascripts/simple_form_extension/redactor.coffee
+++ vendor/assets/javascripts/simple_form_extension/redactor.coffee
@@ -14,14 +14,14 @@
           'unorderedlist', 'orderedlist', 'outdent', 'indent',
           'image', 'video', 'file', 'table', 'link', 'alignment', 'horizontalrule']
         minHeight: 400
+        imageUpload: ["/redactor_rails/pictures", params].join('?')
+        imageGetJson: "/redactor_rails/pictures"
+        fileUpload: ["/redactor_rails/documents", params].join('?')
+        fileGetJson: "/redactor_rails/documents"
         plugins: [
           "fontcolor"
           "fontsize"
         ]
-        imageUpload: ["/redactor_rails/pictures", params].join('?')
-        imageGetJson: "/redactor_rails/pictures"
-        fileUpload: ["/redactor_rails/documents", params].join('?')
-        fileGetJson: "/redactor_rails/documents"
         path: "/assets/redactor-rails"
         css: "style.css"
         lang: "fr"


ComputeProviderKoding: check usage limits before creating a new machine [completes #77485472]

--- workers/social/lib/social/models/computeproviders/koding.coffee
+++ workers/social/lib/social/models/computeproviders/koding.coffee
@@ -45,6 +45,32 @@
     callback null, "Koding is the best #{ client.r.account.profile.nickname }!"

+  getUserPlan = (account)->
+
+    knownPlans = Object.keys PLANS
+    flags = account.globalFlags or []
+
+    PLANS[ do ->
+
+      for plan in knownPlans
+        return plan  if "plan-#{plan}" in flags
+
+      return 'free'
+
+    ]
+
+
+  checkUsage = (usage, plan, storage)->
+
+    err = null
+    if usage.total + 1 > plan.total
+      err = "Total limit of #{plan.total} machines has been reached."
+    else if usage.storage + storage > plan.storage
+      err = "Total limit of #{plan.storage}GB storage limit has been reached."
+
+    if err then return new KodingError err
+
+
   calculateNextLabel = (user, group, label, callback)->

     return callback null, label  if label?
@@ -60,6 +86,7 @@
       limit    : 1
       sort     : createdAt : -1

+
     JMachine.one selector, options, (err, machine)->

       return callback err  if err?
@@ -71,22 +98,35 @@
         callback null, "koding-vm-#{index+1}"

+
   @create = (client, options, callback)->

     { instanceType, label, storage } = options
-    { r: { group, user } } = client
+    { r: { group, user, account } } = client

-    calculateNextLabel user, group, label, (err, label)->
+    storage ?= 3
+    userPlan = getUserPlan account

-      meta =
-        type          : "amazon"
-        region        : "us-east-1"
-        source_ami    : "ami-2651904e"
-        instance_type : "t2.micro"
-        storage_size  : storage ? 3
-        alwaysOn      : no
+    @fetchUsage client, options, (err, usage)->

-      callback null, { meta, label, credential: client.r.user.username }
+      return callback err  if err?
+
+      if err = checkUsage usage, userPlan, storage
+        return callback err
+
+      calculateNextLabel user, group, label, (err, label)->
+
+        meta =
+          type          : "amazon"
+          region        : "us-east-1"
+          source_ami    : "ami-2651904e"
+          instance_type : "t2.micro"
+          storage_size  : storage
+          alwaysOn      : no
+
+        callback null, {
+          meta, label, credential: client.r.user.username
+        }

   @fetchUsage = (client, options, callback)->


alternate fix for navbar

alternate fix for navbar


More thorough sync triggers

More thorough sync triggers

--- core/app/backbone/models/wheel.coffee
+++ core/app/backbone/models/wheel.coffee
@@ -86,7 +86,7 @@
           factlink: fact_id
           opinion: opinion_type
         options.success?()
-        @trigger 'sync', this, response, options
+        @trigger 'sync', this, response, options # TODO: Remove when using Backbone sync
       error: =>
         # TODO: This is not a proper undo. Should be restored to the current
         #       state when the request fails.
@@ -96,6 +96,7 @@
           @turnOffActiveOpinionType()
         options.error?()

+  # TODO: Use Backbone sync here!!
   unsetActiveOpinionType: (opinion_type, options={}) ->
     fact_id = @get('fact_id')
     @turnOffActiveOpinionType()
@@ -107,6 +108,7 @@
         mp_track "Factlink: De-opinionate",
           factlink: fact_id
         options.success?()
+        @trigger 'sync', this, response, options # TODO: Remove when using Backbone sync
       error: =>
         @turnOnActiveOpinionType opinion_type
         options.error?()


[Test] Geo Bypass

[Test] Geo Bypass

--- modules/player/util.coffee
+++ modules/player/util.coffee
@@ -87,7 +87,7 @@

   # Uses youtube-dl to get information of an URL or search term
   getInfo: (query)=>
-    flags = ['--default-search', 'ytsearch', '-i4f', 'bestaudio/best']
+    flags = ['--geo-bypass', '--default-search', 'ytsearch', '-i4f', 'bestaudio/best']
     try
       # get information
       info = await ytdl(query, flags, { maxBuffer: Infinity })


whitespace

whitespace

--- example/mandelbrot.coffee
+++ example/mandelbrot.coffee
@@ -17,7 +17,7 @@
 converger = (->

   c = module.makeFunction "converger", f32, f32, f32, f32, f32, f32
-
+
   one = c.value f32, 1
   two = c.value f32, 2

@@ -26,12 +26,12 @@
   it = c.parameter 2
   cr = c.parameter 3
   ci = c.parameter 4
-
+
   rsq = c.mul r, r
   isq = c.mul i, i

   squares = c.add rsq, isq
-
+
   max = c.value f32, 255

   itAboveMax = c.foGreaterThan it, max
@@ -39,7 +39,7 @@
   squaresAboveFour = c.foGreaterThan squares, c.value f32, 4

   cond = c.or itAboveMax, squaresAboveFour
-
+
   ifDone = c.if cond

   e = ifDone.else


Changing null to undefined. Some versions of IE need undefined as return

--- app/assets/javascripts/application.js.coffee
+++ app/assets/javascripts/application.js.coffee
@@ -313,11 +313,11 @@
   loseChangesMessage = "You have unsaved changes! If you leave the page now, some answers will be lost. Stay on the page for a minute in order for everything to be saved or use the buttons at the bottom of the page."

   window.onbeforeunload = ->
-    if changesUnsaved then loseChangesMessage else null
+    if changesUnsaved then loseChangesMessage else undefined

   if window.addEventListener isnt undefined
     window.addEventListener "beforeunload", (e) ->
-      return null unless changesUnsaved
+      return undefined unless changesUnsaved

       e.returnValue = loseChangesMessage
       loseChangesMessage


Use Coffeescript string interpolation

Use Coffeescript string interpolation

--- app/assets/javascripts/event_rules.js.coffee
+++ app/assets/javascripts/event_rules.js.coffee
@@ -7,18 +7,18 @@
       regexp = new RegExp('new_event_rule', 'g')
       $('ul#event_rules').append(content.replace(regexp, new_id))
       # Setup event autocomplete for new field
-      this.cloudfuji_event_autocomplete('input#event_rules_'+new_id+'_cloudfuji_event')
+      this.cloudfuji_event_autocomplete("input#event_rules_#{new_id}_cloudfuji_event")

     remove_fields: (button) ->
       container = $(button).closest('li.event_rule')
       index = container.data('index')
       # If rule has no id, just remove
-      if $("#event_rules_"+index+"_id").length == 0
+      if $("#event_rules_#{index}_id").length == 0
         container.remove()
       else
         # If rule has an id, mark container as hidden and add _destroy field
         container.hide()
-        container.append($('<input type="text" name="event_rules['+index+'][_destroy]" value="yes">'))
+        container.append($("<input type='text' name='event_rules[#{index}][_destroy]' value='yes'>"))

     cloudfuji_event_autocomplete: (selector = 'input.cloudfuji_event') ->
       $(selector).autocomplete({source: observed_cloudfuji_events, minLength: 0})
@@ -29,8 +29,8 @@
     show_field_group: (select, group_name, key) ->
       # Hide all fields, then show the selected field group
       container = $(select).closest('li.event_rule')
-      container.find('.'+group_name+'_fields').hide()
-      container.find('.'+group_name+'_'+key).show()
+      container.find(".#{group_name}_fields").hide()
+      container.find(".#{group_name}_#{key}").show()

   $(document).ready ->
     event_rules = new EventRules()


fixed #25

fixed #25

--- app/assets/javascripts/hackathons-map.coffee
+++ app/assets/javascripts/hackathons-map.coffee
@@ -9,7 +9,7 @@

 	    map = new google.maps.Map(mapDiv,
 	        center: new google.maps.LatLng(0, 0),
-	        zoom: 1,
+	        zoom: 15,
 	        mapTypeId: google.maps.MapTypeId.ROADMAP
 	    )

@@ -47,7 +47,7 @@

     )
     if (data.length == 1 && data[0].locations.length == 1)
-    	map.setCenter(new google.maps.LatLng(data.locations[0].latitude, data.locations[0].longitude))
+    	map.setCenter(new google.maps.LatLng(data[0].locations[0].latitude, data[0].locations[0].longitude))
     else
     	map.fitBounds(latlngbounds)


adding all the enums to be member variables of the jiffy_enums class

--- app/assets/javascripts/jiffy_enums.js.coffee
+++ app/assets/javascripts/jiffy_enums.js.coffee
@@ -3,6 +3,10 @@

 class window.JiffyEnums
   constructor: (@hash) ->
+    that = this
+    _.each(@hash, (k,v) ->
+      that[v] = k
+    )

   # equavalent to [] in ruby
   get: (key) =>


Small code style fixes for ContextMenuItemView

--- app/coffeescripts/ContextMenuItemView.coffee
+++ app/coffeescripts/ContextMenuItemView.coffee
@@ -9,9 +9,9 @@
     @$el.html @template({text: values.label})  if values.label
     @$el.attr 'class', values.className if values.className
     @$el.attr 'id', values.id if values.id
-    @events = {'click': values.event } if values.event
+    @events = {click: values.event} if values.event
     @render()
-
-  render: () ->
+
+  render: ->
     $("##{@parentId}").append(@el)
-    @
+    @


admin-modal: Changed forgotten button name.

--- client/landing/app/MainApp/sidebar/modals/adminmodal.coffee
+++ client/landing/app/MainApp/sidebar/modals/adminmodal.coffee
@@ -214,7 +214,7 @@
                     content   : inputs.Description.getValue()
                     type      : inputs.Type.getValue()
                   , ->
-                    buttons["Broadcast"].hideLoader()
+                    buttons["Broadcast Message"].hideLoader()

               "Cancel Restart":
                 title         : "Cancel Restart"


Use all available dictionaries

Use all available dictionaries

--- src/ui/dispatcher.coffee
+++ src/ui/dispatcher.coffee
@@ -39,9 +39,12 @@

     require('./version').check()

-    spellchecker.setDictionary(navigator.language)
     require('electron').webFrame.setSpellCheckProvider navigator.language, true, spellCheck: (text) ->
-        spellchecker.isMisspelled(text) != false
+        for dictionary in spellchecker.getAvailableDictionaries()
+            spellchecker.setDictionary(dictionary)
+            if spellchecker.isMisspelled(text) != false
+                return true
+        return false

 handle 'chat_message', (ev) ->
     conv.addChatMessage ev