added autoscroll

added autoscroll

--- app/scripts/controllers/docs.coffee
+++ app/scripts/controllers/docs.coffee
@@ -71,13 +71,15 @@
         $scope.getDocPartial = (docName) ->
             # loads all of the markdown partials that have been
             # precompiled into HTML
+
             "views/docs/#{docName}.html"

         $scope.createToC = (docName) ->
             # since we edit the docs in markdown, headers, subheaders,
             # etc. may change.  For this reason, we use this function to
             # build the table of contents style side bar on the fly
-            section = angular.element("section #{docName}")
+            section = angular.element(" ##{docName}")
+
             h2 = angular.element(section).find("h2")

             sideBarSection = angular.element("anchor #{docName}")
@@ -88,21 +90,22 @@
                                         .attr("class", "level-2 list-group hidden")
                 sideBarSection.append(level2headers)
                 for header in h2
-                    debugger
+
                     title = angular.element('<a>')
                                     .attr('href', "##{header.getAttribute('id')}")
                                     .attr('class', "level-2 list-group-item")
                     level2headers.append(title)

-                    # debugger
+
                     "foo"

             href = docName
-
+

             for section in $("#sidebar").children()
                 href = $(section).children("a.level-1")[0].hash.replace("#", "")
+
                 sectionContent = $("##{href}").children("section, h2, h3, h4, h5")
                 if sectionContent.length
                     $(section).append("<div id='lvl-2-#{href}' class='level-2 list-group'>")
@@ -128,7 +131,7 @@
                         $("#sidebar").find("div.level-2").addClass("hidden")

         $scope.gotoAnchor = (doc) ->
-
+
             if $location.hash() isnt doc
                 $location.hash(doc)
             else


retrieve only articles for current year from API

--- app/scripts/controllers/main.coffee
+++ app/scripts/controllers/main.coffee
@@ -4,7 +4,9 @@
     .controller 'MainCtrl', ($scope, $http, $filter, Restangular) ->
         today = $scope.today = new Date()
         month = $filter('date')(today, "MMMM")
+        monthDigit = $filter('date')(today, "MM")
         year  = $filter('date')(today, "yyyy")
+        day = $filter('date')(today, "dd")
         $scope.month = []
         $scope.year  = []
         # Date information
@@ -13,16 +15,17 @@
           month : month
           year : year
         # Loads data from API
-        (do (Restangular.all 'articles').getList).then (data) =>
+        filter = 'where={"ref_date":"' + year + '"}'
+        (do (Restangular.all "articles?#{filter}").getList).then (data) =>
           $scope.days = []
           _.map data[0], (article) =>
-            year = parseInt article['ref_date'][0]
-            if year is do today.getFullYear
-              month = (parseInt article['ref_date'][1]) - 1
-              day = parseInt article['ref_date'][2]
-              article['reference_date'] = new Date year, month, day
-              if month is do today.getMonth
-                if day is do today.getDate
+            a_year = article['ref_date'][0]
+            if a_year is year
+              a_month = article['ref_date'][1]
+              a_day = article['ref_date'][2]
+              article['reference_date'] = new Date a_year, a_month, a_day
+              if a_month is monthDigit
+                if a_day is day
                   $scope.days.push article
                 else
                   $scope.month.push article


Add isRendered method in view controller

--- app/src/base/view_controller.coffee
+++ app/src/base/view_controller.coffee
@@ -29,6 +29,7 @@
   constructor: (params = {}, routedUrl = "") ->
     @params = _.defaults(params, @defaultParams)
     @routedUrl = routedUrl
+    @_isRendered = no
     # bind all methods to self
     for key, value of @
       if _.isFunction(value) and value != @constructor
@@ -52,6 +53,7 @@
     @emit 'beforeRender', {sender: @}
     render @viewPath(), @, (html) =>
       selector.html(html)
+      @_isRendered = yes
       do @onAfterRender
       @emit 'afterRender', {sender: @}

@@ -113,3 +115,5 @@

   # Called when the view controller is detached from a parent view controller
   onDetach: ->
+
+  isRendered: -> @_isRendered


removed show button manager

removed show button manager

--- js-library/app/js/models/fact.coffee
+++ js-library/app/js/models/fact.coffee
@@ -1,21 +1,6 @@
 highlight_time_on_load    = 1500
 highlight_time_on_in_view = 1500
 delay_between_highlight_and_show_button_open = 400
-
-
-class ShowButtonManager
-  constructor: (@dom_events) ->
-    @show_button = new Factlink.ShowButton @dom_events
-
-  set_coordinates: (top, left) =>
-    @show_button.setCoordinates(top, left)
-
-  openShowButton:  ->  @show_button.show()
-  closeShowButton: ->  @show_button.hide()
-
-  startLoading: -> @show_button.startLoading()
-
-  destroy: -> @show_button.destroy()

 class Highlighter
   constructor: (@$elements) ->
@@ -57,7 +42,7 @@

     @highlighter = new Highlighter $(@elements)

-    @show_button_manager = new ShowButtonManager
+    @show_button = new Factlink.ShowButton
       mouseenter: => @onFocus()
       mouseleave: => @onBlur()
       click:      => @openFactlinkModal()
@@ -78,18 +63,18 @@
   onBlur: -> @attention_span.neglect()
   onFocus: (e) =>
     if e?
-      @show_button_manager.set_coordinates($(e.target).offset().top, e.pageX)
+      @show_button.setCoordinates($(e.target).offset().top, e.pageX)
     @attention_span.attend()

   startEmphasis: ->
     @highlighter.highlight()
-    @show_button_manager.openShowButton()
+    @show_button.show()

   stopEmphasis: =>
     return if @shouldHaveEmphasis()

     @highlighter.dehighlight()
-    @show_button_manager.closeShowButton()
+    @show_button.hide()

   shouldHaveEmphasis: =>
     @attention_span.has_attention() || @_loading
@@ -100,7 +85,7 @@

   startLoading: ->
     @_loading = true
-    @show_button_manager.startLoading()
+    @show_button.startLoading()

   stopLoading: ->
     @_loading = false
@@ -114,4 +99,4 @@

       $el.remove()

-    @show_button_manager.closeShowButton()
+    @show_button.destroy()


Update to jQuery IIFE

Update to jQuery IIFE

--- js/jquery.mobile508datepicker.coffee
+++ js/jquery.mobile508datepicker.coffee
@@ -3,7 +3,7 @@
 #	Github: https://github.com/jsdev/mobile508datepicker
 #	MIT License: as is, feel free to fork =)
 #	Tested on: IOS, Android, Surface, Modern Browsers, IE10+, IE9
-#
+#
 (($) ->
   "use strict"
   $.fn.extend
@@ -14,8 +14,8 @@
         MAX: new Date(new Date().setFullYear(currentDate.getFullYear() + 10)) # years ahead

       defaults = null
-
-      #jshint multistr: true
+
+      #jshint multistr: true
       $el = $("
 \t\t\t\t\tClose \t\t\t\t\t
Today
 \t\t\t\t\t

 \t\t\t\t\t<button id=\"set-btn\" data-theme=\"b\" class=\"ui-btn-hidden\" data-disabled=\"false\">SET</button> \t\t\t\t\t
")
       buildEl = ->
         $("body").append $el
@@ -67,7 +67,7 @@
         "Fr "
         "Sa "
       ]
-
+
       #WEEKDAYS = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
       buildDOM = ->
         i = undefined
@@ -135,7 +135,7 @@

       updateHeading = ->
         calcDate = setDate()
-
+
         #$setBtn.prev('span').find('span').text('Set as: ' + [dateChosen.month+1, dateChosen.day, dateChosen.year].join('/'));
         heading.innerHTML = (if calcDate.toDateString() is currentDate.toDateString() then "Today" else WEEKDAYS[calcDate.getDay()])

@@ -356,12 +356,12 @@
       ).on "keydown", (e) ->
         close()  if e.which is 27

-
+
       #Iterate over the current set of matched elements
       @each ->
         $this = $(this)
         $dp = $("#date-picker")
-
+
         #THIS WILL BUILD IT ONCE, vs. only once foreach in collection
         $dp.length or buildEl()
         $this.on("click", (e) ->
@@ -398,4 +398,4 @@
         $b.scrollTop scrollTop

-) jQuery
+)(jQuery)


Fix spaces

Fix spaces

--- js/tests/filters/sanitizeSpec.coffee
+++ js/tests/filters/sanitizeSpec.coffee
@@ -110,11 +110,11 @@
 		expect(out).toBe(url)

-        it 'should validate an url', =>
-                url = 'google.de/someting#XML=123'
-                out = @filter(url)
+	it 'should validate an url', =>
+		url = 'google.de/something#XML=123'
+		out = @filter(url)

-                expect(out).toBe(url)
+		expect(out).toBe(url)

 	it 'should return null if xss null', =>


use events to poll

use events to poll

--- src/adapter.coffee
+++ src/adapter.coffee
@@ -26,6 +26,7 @@
     throw new Error('HUBOT_SYMPHONY_PUBLIC_KEY undefined') unless process.env.HUBOT_SYMPHONY_PUBLIC_KEY
     throw new Error('HUBOT_SYMPHONY_PRIVATE_KEY undefined') unless process.env.HUBOT_SYMPHONY_PRIVATE_KEY
     throw new Error('HUBOT_SYMPHONY_PASSPHRASE undefined') unless process.env.HUBOT_SYMPHONY_PASSPHRASE
+    this.on 'poll', (id) => @_pollDataFeed(id)

   send: (envelope, strings...) ->
     @robot.logger.debug "Send"
@@ -48,20 +49,21 @@
         @robot.emit 'error', new Error("Unable to resolve identity: #{err}")
     @symphony.createDatafeed()
       .then (response) =>
-        @emit "connected"
-        @_pollDatafeed(response.id)
+        @robot.logger.info "Created datafeed: #{response.id}"
+        @emit 'connected'
+        @emit 'poll', response.id
       .fail (err) =>
         @robot.emit 'error', new Error("Unable to create datafeed: #{err}")

   _pollDatafeed: (datafeedId) =>
     @robot.logger.debug "Polling datafeed #{datafeedId}"
-    while true
-      @symphony.readDatafeed(datafeedId)
-        .then (response) =>
-          @robot.logger.debug "Received #{response.length} datafeed messages"
-          @_receiveMessage msg for msg in response when msg.v2messageType = 'V2Message'
-        .fail (err) =>
-          @robot.emit 'error', new Error("Unable to read datafeed #{datafeedId}: #{err}")
+    @symphony.readDatafeed(datafeedId)
+      .then (response) =>
+        @robot.logger.debug "Received #{response.length} datafeed messages"
+        @_receiveMessage msg for msg in response when msg.v2messageType = 'V2Message'
+        @emit 'poll', response.id
+      .fail (err) =>
+        @robot.emit 'error', new Error("Unable to read datafeed #{datafeedId}: #{err}")

   _receiveMessage: (message) =>
     user = @symphony.getUser(message.fromUserId)


Add missing path require

Add missing path require

--- src/apm-cli.coffee
+++ src/apm-cli.coffee
@@ -1,5 +1,9 @@
+{spawn} = require 'child_process'
+path = require 'path'
+
 _ = require 'underscore-plus'
 colors = require 'colors'
+npm = require 'npm'
 optimist = require 'optimist'
 wordwrap = require 'wordwrap'

@@ -95,9 +99,6 @@
       callback()

 getPythonVersion = (callback) ->
-  npm = require 'npm'
-  {spawn} = require 'child_process'
-
   npmOptions =
     userconfig: config.getUserConfigPath()
     globalconfig: config.getGlobalConfigPath()
@@ -122,9 +123,6 @@
       callback(version)

 getGitVersion = (callback) ->
-  npm = require 'npm'
-  {spawn} = require 'child_process'
-
   npmOptions =
     userconfig: config.getUserConfigPath()
     globalconfig: config.getGlobalConfigPath()


activity: remove unused "ContentDisplayStatusUpdate" require :bug: (leaking StatusActivityItemView)

--- client/activity/lib/index.coffee
+++ client/activity/lib/index.coffee
@@ -1,12 +1,12 @@
-kd = require 'kd'
+kd              = require 'kd'
 ActivityAppView = require './activityappview'
-ContentDisplayStatusUpdate = require './contentdisplays/contentdisplaystatusupdate'
-remote = require('app/remote').getInstance()
-globals = require 'globals'
-getGroup = require 'app/util/getGroup'
-checkFlag = require 'app/util/checkFlag'
-AppStorage = require 'app/appstorage'
-AppController = require 'app/appcontroller'
+remote          = require('app/remote').getInstance()
+globals         = require 'globals'
+getGroup        = require 'app/util/getGroup'
+checkFlag       = require 'app/util/checkFlag'
+AppStorage      = require 'app/appstorage'
+AppController   = require 'app/appcontroller'
+
 require('./routehandler')()

 module.exports = class ActivityAppController extends AppController


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/bounded.coffee
+++ src/bounded.coffee
@@ -41,8 +41,7 @@
     collisionMargin: Point(0, 0)

   ###*
-  The position of this game object. By default it is the top left point.
-  Redefining the center method will change the relative position.
+  Distance between two objects. Proxies

   player = Core


I am even stupider than I thought

I am even stupider than I thought

--- coffee/Game.coffee
+++ coffee/Game.coffee
@@ -119,6 +119,8 @@
             y = Math.max(Math.min(y, @height - s / 2), s / 2)
             obj.damage.groups.push("enemy")
             obj.damage.energy = 6
+            # I don't set obj.damage.max_energy here, cause I want to use the
+            # different drawing of an enemy, caused by this missing of energy
             obj.shooting.shell_group = "enemy"
             m.pos.Set(x + m.size.x, y)
             m.vel.Set(-100 + 40 * Math.random(), 0)


Potential fix for issue #22.

Potential fix for issue #22.

--- coffeequate/src/operators.coffee
+++ coffeequate/src/operators.coffee
@@ -359,52 +359,120 @@
 				negatedTerms.push(newMul)

 			negatedTermsEquatable = new Add(negatedTerms...) unless negatedTerms.length == 0
+			nonNegatedTermsEquatable = new Add(termsNotContainingVariable...) unless termsNotContainingVariable.length == 0
 			factorisedEquatable = new Add(factorised...) unless factorised.length == 0
 			factorisedSquaresEquatable = new Add(factorisedSquares...) unless factorisedSquares.length == 0
+			inversedEquatable = new Add(inversed...) unless inversed.length == 0
+			inversedSquaresEquatable = new Add(inversedSquares...) unless inversedSquares.length == 0
+
+			# Let's just... enumerate everything. That will probably work.
+
+			if negatedTerms.length == 0
+				negatedTermsEquatable = new terminals.Constant("0")

 			if factorisedSquares.length == 0
+				## Outdated comment follows:
 				# We now have terms on the other side of the equation (negatedTermsEquatable) and
 				# terms factorised out from this side of the equation (factorisedEquatable).
 				# (factorisedEquatable * v) = negatedTermsEquatable
 				# Hence the solution is simply (negatedTermsEquatable * (factorisedEquatable ** -1)).
-				if factorised.length > 0
-					newPow = new Pow(factorisedEquatable, "-1")
-					newPow = newPow.simplify()
-					if negatedTermsEquatable?
-						newMul = new Mul(negatedTermsEquatable, newPow)
-						newMul = newMul.simplify()
-						return [newMul]
-					else
-						return [newPow]
-				else
-					throw new AlgebraError(expr.toString(), variable)
+				## Saved for posterity. New comment follows:
+				# There are no squares in the equation.
+				if factorised.length == 0
+					# There are no standalone variables in the equation.
+					if inversed.length == 0
+						# There are no standalones or squares or inversed variables.
+						if inversedSquares.length == 0
+							# There is nothing. There is nothing here. All is lost.
+							throw new AlgebraError(expr.toString(), variable)
+						else
+							# We have only inversed squares.
+							# -a = b/v**2
+							# v = +/(b/-a)**1/2
+							answer = new Mul(new Pow(inversedSquaresEquatable, "1/2"), new Pow(negatedTermsEquatable, "-1/2"))
+							a1 = new Mul(-1, answer.copy())
+							a1 = a1.expandAndSimplify()
+							a2 = answer.expandAndSimplify()
+							if a1.equals?(a2)
+								return [a1]
+							else
+								return [a1, a2]
+					else
+						# There are no standalones, but there are inversed variables.
+						if inversedSquares.length == 0
+							# We only have inversed variables.
+							# -a = b/v
+							# v = b/-a
+							answer = new Mul(inversedEquatable, negatedTermsEquatable)
+							return [answer.expandAndSimplify()]
+						else
+							# We have inversed variables and inversed squares.
+							# -a = b/v + c/v**2
+							# Ewwwww
+							# Ewwwwwwwwwwwwwwwwwww
+							# 0 = a + b/v + c/v**2
+							# 0 = a v**2 + b v + c
+							newAdd = new Add(new Mul(nonNegatedTermsEquatable, new Pow(new terminals.Variable(variable), 2)),
+								new Mul(inversedEquatable, new terminals.Variable(variable)),
+								inversedSquaresEquatable)
+							console.log("Recursing into Add.solve with (#{newAdd})")
+							return newAdd.solve(variable)
+				else if inversed.length == 0
+					# There are standalone variables, but there aren't any inversed ones.
+					if inversedSquares.length == 0
+						# There are no inversed squares, so there are just standalone variables.
+						# -a = b v
+						# v = -a / b
+						answer = new Mul(negatedTermsEquatable, new Pow(factorisedEquatable, "-1"))
+						return [answer.expandAndSimplify()]
+					else
+						# There are inversed squares and standalone variables.
+						# That's a cubic, c'mon.
+						# Technically, this is solvable if negatedTerms.length == 0, but
+						# is that ever likely to actually happen?
+						## FIXME
+						throw new AlgebraError(expr.toString(), variable, " (not supported)")
+				# else if inversedSquares.length == 0
+					# There are standalone variables and inversed variables, but there aren't any
+					# inversed squares.
+					# This actually exhausts all possibilities, so I'll comment this else out for clarity.
+				else
+					# There are standalone variables and inversed variables and inversed squares,
+					# so this is unsolvable.
+					throw new AlgebraError(expr.toString(), variable, " (not supported)")
 			else if factorised.length == 0
-				# We now have terms on the other side of the equation (negatedTermsEquatable) and
-				# terms factorised out from this side of the equation (factorisedSquaresEquatable).
-				# (factorisedSquaresEquatable * (v ** 2)) = negatedTermsEquatable
-				# Hence the solution is simply \pm ((negatedTermsEquatable * (factorisedSquaresEquatable ** -1)) ** 1/2).
-				if factorisedSquares.length > 0
-					newPow = new Pow(factorisedSquaresEquatable, "-1")
-					newPow = newPow.simplify()
-					if negatedTermsEquatable?
-						newMul = new Mul(negatedTermsEquatable, newPow)
-						newerPow = new Pow(newMul, "1/2")
-						negatedNewerPow = new Mul("-1", newerPow)
-						negatedNewerPow = negatedNewerPow.simplify()
-						newerPow = newerPow.simplify()
-						return [newerPow, negatedNewerPow]
-					else
-						newerPow = new Pow(newPow, "1/2")
-						negatedNewerPow = new Mul("-1", newerPow)
-						negatedNewerPow = negatedNewerPow.simplify()
-						newerPow = newerPow.simplify()
-						return [newerPow, negatedNewerPow]
-				else
-					throw new AlgebraError(expr.toString(), variable)
-			else
+				# We have squared terms, but no standalone terms.
+				if inversed.length == 0
+					# We have squared terms, but no standalone terms or inversed terms.
+					if inversedSquares.length == 0
+						# There are no inversed squares, so there is only squared terms.
+						# -a = v**2
+						answer = new Pow(negatedTermsEquatable, "1/2")
+						a1 = new Mul("-1", answer.copy())
+						a1 = a1.expandAndSimplify()
+						a2 = answer.expandAndSimplify()
+						if a1.equals?(a2)
+							return [a1]
+						else
+							return [a1, a2]
+					else
+						# We have squared terms and inverse squared terms.
+						# That is a quartic, and as quartics are a danger to the very moral fabric of our
+						# society, we don't solve them here.
+						## FIXME: This is solvable if negatedTerms.length == 0.
+						throw new AlgebraError(expr.toString(), variable, " (not supported)")
+				else
+					# We have squares and we have inversed variables, so this is usually unsolvable, except if
+					# inversed squares and negated terms are both of 0 length.
+					## FIXME: Deal with that situation.
+					throw new AlgebraError(expr.toString(), variable, " (not supported)")
+			else
+				# There are squares and standalone variables. Unsolvable if we have any inverses whatsoever.
+				if inversed.length > 0 or inversedSquares.length > 0
+					throw new AlgebraError(expr.toString(), variable, " (not supported)")
+
 				# We have a quadratic equation.
 				# ((factorisedSquaresEquatable) * (v ** 2)) + (factorisedEquatable * v) + (nonNegatedTerms) = 0
-				nonNegatedTermsEquatable = new Add(termsNotContainingVariable...) unless termsNotContainingVariable.length == 0
 				if nonNegatedTermsEquatable?
 					# a = fSE
 					# b = fE


Add missing `return`

Add missing `return`

--- app._coffee
+++ app._coffee
@@ -81,11 +81,11 @@
       message: 'Not found'

   content = Content.getById id, _
-  if content?
-    res.json 200, content
-  res.json 404, error:
-    code: 404
-    message: 'Not found'
+  if not content?
+    return res.json 404, error:
+      code: 404
+      message: 'Not found'
+  res.json 200, content

 app.get /^\/(https?:\/\/.+)/, (req, res, _) ->
   url = req.params[0]


Base item pointer impl scrollable items bugs fixes

--- impl/base/level0/item/pointer.coffee
+++ impl/base/level0/item/pointer.coffee
@@ -77,7 +77,7 @@
 						break

 				# test content item
-				if item instanceof Scrollable and item._contentItem
+				if item instanceof Scrollable and item._contentItem and not (result & STOP_ASIDE_PROPAGATION)
 					result |= checkItem(
 						type,
 						item._contentItem,
@@ -86,7 +86,7 @@
 						x - item.contentX * parentScale, y - item.contentY * parentScale,
 						scale
 					)
-					if result & (STOP_PROPAGATION | STOP_ASIDE_PROPAGATION)
+					if result & STOP_PROPAGATION
 						return result

 			# test this child
@@ -118,8 +118,8 @@
 		# support press event
 		Device.onPointerPress do ->
 			onItem = (item) ->
-				event._ensureRelease = event._ensureMove = event._stopPropagation = true
 				if item._impl.capturePointer & PRESS
+					event._ensureRelease = event._ensureMove = event._stopPropagation = true
 					emitSignal item.pointer, 'onPress', event
 					pressedItems.push item
 					if event._ensureRelease
@@ -128,7 +128,8 @@
 						itemsToMove.push item
 					if event._stopPropagation
 						return STOP_PROPAGATION
-				return getEventStatus()
+					return getEventStatus()
+				0

 			(e) ->
 				event._checkSiblings = false
@@ -139,24 +140,27 @@
 		Device.onPointerRelease do ->
 			onItem = (item) ->
 				data = item._impl
-				if data.capturePointer & RELEASE
+				{capturePointer} = data
+				if capturePointer & RELEASE
 					emitSignal item._pointer, 'onRelease', event
-				if data.capturePointer & PRESS
+				if capturePointer & PRESS
 					index = itemsToRelease.indexOf item
 					if index >= 0
 						itemsToRelease[index] = null
-				if data.capturePointer & CLICK
+				if capturePointer & CLICK
 					if utils.has(pressedItems, item)
 						emitSignal item.pointer, 'onClick', event
-				if event._stopPropagation
-					return STOP_PROPAGATION
-				return getEventStatus()
+				if capturePointer & (RELEASE | CLICK)
+					if event._stopPropagation
+						return STOP_PROPAGATION
+					return getEventStatus()
+				0

 			(e) ->
 				event._stopPropagation = false
 				event._checkSiblings = false

-				captureItems CLICK, impl.window, e._x, e._y, onItem
+				captureItems RELEASE | CLICK, impl.window, e._x, e._y, onItem

 				unless event._stopPropagation
 					for item in itemsToRelease by -1
@@ -176,25 +180,27 @@

 			onItem = (item) ->
 				data = item._impl
-				if data.capturePointer & MOVE
+				{capturePointer} = data
+				if capturePointer & (ENTER | EXIT | MOVE)
 					data.pointerMoveFlag = flag
-				if data.capturePointer & (ENTER | EXIT) and not data.pointerHover
+				if capturePointer & (ENTER | EXIT) and not data.pointerHover
 					data.pointerHover = true
 					hoverItems.push item
 					emitSignal item.pointer, 'onEnter', event
-
-				if data.capturePointer & MOVE
+				if capturePointer & MOVE
 					emitSignal item._pointer, 'onMove', event
-				if event._stopPropagation
-					return STOP_PROPAGATION
-				return getEventStatus()
+				if capturePointer & (ENTER | EXIT | MOVE)
+					if event._stopPropagation
+						return STOP_PROPAGATION
+					return getEventStatus()
+				0

 			(e) ->
 				event._stopPropagation = false
 				event._checkSiblings = false
 				flag = (flag % 2) + 1

-				captureItems MOVE, impl.window, e._x, e._y, onItem
+				captureItems ENTER | EXIT | MOVE, impl.window, e._x, e._y, onItem

 				for item in itemsToMove
 					if event._stopPropagation
@@ -225,9 +231,10 @@
 				if item._impl.capturePointer & WHEEL
 					if (pointer = item._pointer) and not signal.isEmpty(pointer.onWheel)
 						emitSignal pointer, 'onWheel', event
-					if event._stopPropagation
-						return STOP_PROPAGATION
-				return getEventStatus()
+						if event._stopPropagation
+							return STOP_PROPAGATION
+						return getEventStatus()
+				0

 			(e) ->
 				event._checkSiblings = false
@@ -242,9 +249,9 @@
 		onRelease: RELEASE = 1 << i++
 		onMove: MOVE = 1 << i++
 		onWheel: WHEEL = 1 << i++
-		onClick: CLICK = (1 << i++) | PRESS | RELEASE
-		onEnter: ENTER = (1 << i++) | MOVE
-		onExit: EXIT = (1 << i++) | MOVE
+		onClick: CLICK = 1 << i++
+		onEnter: ENTER = 1 << i++
+		onExit: EXIT = 1 << i++
 		# onDragStart: 1 << i++
 		# onDragEnd: 1 << i++
 		# onDragEnter: 1 << i++


Ensure that form element are well disabled to not submit them

As they're not handled by the backend

--- app/assets/javascripts/admin/enterprise_fees/directives/ensure_calculator_preferences_match_type.js.coffee
+++ app/assets/javascripts/admin/enterprise_fees/directives/ensure_calculator_preferences_match_type.js.coffee
@@ -9,9 +9,9 @@
       settings = element.parent().parent().find('div.calculator-settings')
       if value == orig_calculator_type
         settings.show()
-        settings.find('input').prop 'disabled', false
+        settings.find('input, select').prop 'disabled', false
       else
         settings.hide()
-        settings.find('input').prop 'disabled', true
+        settings.find('input, select').prop 'disabled', true
       return
     return


Send IIP values only once, refs #49

Send IIP values only once, refs #49

--- components/ConnectRuntime.coffee
+++ components/ConnectRuntime.coffee
@@ -118,10 +118,6 @@
       return unless @connected
       runtime.sendGraph 'removeedge', @convertEdge id, edge.detail
     , false
-    editor.addEventListener 'addinitial', (iip) =>
-      return unless @connected
-      runtime.sendGraph 'addinitial', @convertInitial id, iip.detail
-    , false
     editor.addEventListener 'removeinitial', (iip) =>
       return unless @connected
       runtime.sendGraph 'removeinitial', @convertInitial id, iip.detail


increased logging throttling limit to 50 msgs/s

--- proxy.coffee
+++ proxy.coffee
@@ -1,5 +1,5 @@
 log = do ->
-  N = 20; T = 1000 # log no more than N log messages per T milliseconds
+  N = 50; T = 1000 # log no more than N log messages per T milliseconds
   n = t = 0
   (s) ->
     if (t1 = +new Date) - t > T then t = t1; n = 1


fix bug with ctx.opts bleedover across multiple ctx.push calls within same binding/reaction

--- src/context.coffee
+++ src/context.coffee
@@ -23,9 +23,10 @@
   push: (data) -> switch @kind
     when 'rpc', 'action' then @node.do(data, @opts)
     else
-      @node.merge(data, @opts)
+      opts = Object.assign {}, @opts # make a copy
+      @node.merge(data, opts)
       diff = @node.change if @node.changed
-      try await @node.commit(@opts)
+      try await @node.commit(opts)
       catch err then throw @error err
       return diff


call redis createClient without parameters when settings are ommited

this will create a client with the default port, 6379, on the local host

--- pushd.coffee
+++ pushd.coffee
@@ -16,6 +16,8 @@
     redis = require('redis').createClient(settings.server.redis_socket)
 else if settings.server.redis_port? or settings.server.redis_host?
     redis = require('redis').createClient(settings.server.redis_port, settings.server.redis_host)
+else
+    redis = require('redis').createClient()
 if settings.server.redis_db_number?
     redis.select(settings.server.redis_db_number)


Document ATOM_REPOS_HOME

Document ATOM_REPOS_HOME

Close #84

--- src/develop.coffee
+++ src/develop.coffee
@@ -29,7 +29,8 @@

       Clone the given package's Git repository to ~/github/<package_name>,
       install its dependencies, and link it for development to
-      ~/.atom/packages/dev/<package_name>.
+      ~/.atom/packages/dev/<package_name>. The default folder to clone packages
+      into can be overridden using the ATOM_REPOS_HOME environment variable.

       Once this command completes you can open a dev window from atom using
       cmd-shift-o to run the package out of the newly cloned repository.


Copy resource files for panels

Copy resource files for panels

--- SmartRemoteControl/Gruntfile.coffee
+++ SmartRemoteControl/Gruntfile.coffee
@@ -1,6 +1,6 @@
 envs =
   android:
-    basePath: 'file:///android_asset'
+    basePath: 'file:///android_asset/'
   test:
     basePath: null

@@ -31,7 +31,7 @@

       panels:
         cwd: 'assets-src/panels/'
-        src: [ '!**/*.stylus', '!**/*.coffee', '!**/*.jade' ]
+        src: [ '**/*', '!**/*.stylus', '!**/*.coffee', '!**/*.jade' ]
         dest: 'assets/panels/'
         expand: true


Port example to Process API

Port example to Process API

--- examples/http/HelloController.coffee
+++ examples/http/HelloController.coffee
@@ -1,28 +1,19 @@
 noflo = require "noflo"

-class HelloController extends noflo.Component
-    description: "Simple controller that says hello, user"
-
-    constructor: ->
-        @request = null
-
-        @inPorts =
-            in: new noflo.Port()
-        @outPorts =
-            out: new noflo.Port()
-            data: new noflo.Port()
-
-        @inPorts.in.on "data", (data) =>
-            @request = data
-        @inPorts.in.on "disconnect", (data) =>
-            @outPorts.out.send @request
-            @outPorts.out.disconnect()
-
-            @outPorts.data.send
-                locals:
-                    string: "Hello, #{@request.req.remoteUser}"
-            @request = null
-            @outPorts.data.disconnect()
-
 exports.getComponent = ->
-    new HelloController()
+  c = new noflo.Component
+  c.description = "Simple controller that says hello, user"
+  c.inPorts.add 'in',
+    datatype: 'object'
+  c.outPorts.add 'out',
+    datatype: 'object'
+  c.outPorts.add 'data',
+    datatype: 'object'
+  c.process (input, output) ->
+    return unless input.hasData 'in'
+    request = input.getData 'in'
+    output.sendDone
+      out: request
+      data:
+        locals:
+          string: "Hello, #{request.req.remoteUser}"


Enable using regex as filter.

Enable using regex as filter.

--- src/filters.coffee
+++ src/filters.coffee
@@ -1,4 +1,11 @@
 minimatch = require 'minimatch'
+
+# Returns whether the string {str} matches the filter {filter}.
+matches = (str, filter) ->
+  if filter instanceof RegExp
+    filter.test str
+  else
+    minimatch str, filter

 module.exports =
   class Filters
@@ -7,5 +14,5 @@

     @fieldMatchFilter: (filter, value) ->
       for k, v of filter
-        return false unless value[k]? and minimatch value[k], v
+        return false unless value[k]? and matches value[k], v
       true


Specify hostname for server app.

Specify hostname for server app.

--- fetsy-hammertag/server/server.coffee
+++ fetsy-hammertag/server/server.coffee
@@ -50,8 +50,10 @@

 ## Connect to database and start server

+hostname = undefined
 port = 8080
 database.connect()
-app.listen port, ->
-    debug "Example app listening on http://localhost:#{port}/"
+app.listen port, hostname, ->
+    url = "http://#{hostname or 'localhost'}:#{port}/"
+    debug "FeTSy-Hammertag listening on #{url}"
     return


:art: Clear up the matching function

:art: Clear up the matching function

--- src/helpers.coffee
+++ src/helpers.coffee
@@ -189,32 +189,34 @@
   event

 # bindingKeystrokes and userKeystrokes are arrays of keystrokes
+# e.g. ['crtl-y', 'ctrl-x', '^x']
 exports.keystrokesMatch = (bindingKeystrokes, userKeystrokes) ->
   userKeystrokeIndex = -1
   userKeystrokesHasKeydownEvent = false
-  matchesNextStroke = (stroke) ->
+  matchesNextUserKeystroke = (bindingKeystroke) ->
     while userKeystrokeIndex < userKeystrokes.length - 1
       userKeystrokeIndex += 1
       userKeystroke = userKeystrokes[userKeystrokeIndex]
       isKeydownEvent = not userKeystroke.startsWith('^')
       userKeystrokesHasKeydownEvent = true if isKeydownEvent
-      if stroke is userKeystroke
+      if bindingKeystroke is userKeystroke
         return true
       else if isKeydownEvent
         return false
     null

   for bindingKeystroke in bindingKeystrokes
-    doesMatch = matchesNextStroke(bindingKeystroke)
+    doesMatch = matchesNextUserKeystroke(bindingKeystroke)
     if doesMatch is false
       return false
     else if doesMatch is null
-      # If there are only keyup events, it will partial match everything :/
+      # Make userKeystrokes with only keyup events doesn't match everything
       if userKeystrokesHasKeydownEvent
         return PartialMatch
       else
         return false

+  # Prevent binding of ['a'] from exact matching a user pattern of ['a', '^a', 'b', '^b']
   while userKeystrokeIndex < userKeystrokes.length - 1
     userKeystrokeIndex += 1
     return false unless userKeystrokes[userKeystrokeIndex].startsWith('^')


Document the History API

Document the History API

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

 TransactionAborted = new Error("Transaction Aborted")

+# Private: Manages undo/redo for {TextBuffer}
 module.exports =
 class History extends Serializable
   @registerDeserializers(Transaction, BufferPatch)
@@ -14,15 +15,19 @@

   constructor: (@buffer, @undoStack=[], @redoStack=[]) ->

+  # Private: Used by {Serializable} during serialization
   serializeParams: ->
     undoStack: @undoStack.map (patch) -> patch.serialize()
     redoStack: @redoStack.map (patch) -> patch.serialize()

+  # Private: Used by {Serializable} during deserialization
   deserializeParams: (params) ->
     params.undoStack = params.undoStack.map (patchState) => @constructor.deserialize(patchState)
     params.redoStack = params.redoStack.map (patchState) => @constructor.deserialize(patchState)
     params

+  # Private: Called by {TextBuffer} to store a patch in the undo stack. Clears
+  # the redo stack
   recordNewPatch: (patch) ->
     if @currentTransaction?
       @currentTransaction.push(patch)
@@ -30,6 +35,7 @@
       @undoStack.push(patch)
     @clearRedoStack()

+  # Public: Undoes the last operation. If a transaction is in progress, aborts it.
   undo: ->
     if @currentTransaction?
       @abortTransaction()
@@ -38,12 +44,17 @@
       @redoStack.push(inverse)
       inverse.applyTo(@buffer)

+  # Public: Redoes the last operation.
   redo: ->
     if patch = @redoStack.pop()
       inverse = patch.invert(@buffer)
       @undoStack.push(inverse)
       inverse.applyTo(@buffer)

+  # Public: Wraps the given function in a transaction, meaning all changes will
+  # be undone/redone at the same time. The transaction will be aborted if the
+  # function throws an exception. The function's execution will be halted if
+  # ::abortTransaction is called.
   transact: (fn) ->
     @beginTransaction()
     try
@@ -59,15 +70,19 @@
       else
         throw error

+  # Public: Starts an open-ended transaction. Call ::commitTransaction or
+  # ::abortTransaction to complete it.
   beginTransaction: ->
     if ++@transactionDepth is 1
       @currentTransaction = new Transaction()

+  # Public: Commits an outstanding transaction.
   commitTransaction: ->
     if --@transactionDepth is 0
       @undoStack.push(@currentTransaction) if @currentTransaction.hasBufferPatches()
       @currentTransaction = null

+  # Public: Aborts an outstanding transaction.
   abortTransaction: ->
     if @transactCallDepth is 0
       inverse = @currentTransaction.invert(@buffer)
@@ -77,11 +92,14 @@
     else
       throw TransactionAborted

+  # Public: Returns whether the buffer is currently in a transaction.
   isTransacting: ->
     @currentTransaction?

+  # Public: Clears the undo stack
   clearUndoStack: ->
     @undoStack.length = 0

+  # Public: Clears the redo stack
   clearRedoStack: ->
     @redoStack.length = 0


Add some punctuation to our grammar file.

Grammar now understands '.' and ',' punctuation.

--- grammars/dart.cson
+++ grammars/dart.cson
@@ -33,6 +33,9 @@
     'include': '#comments'
   }
   {
+    'include': '#punctuation'
+  }
+  {
     'include': '#annotations'
   }
   {
@@ -246,10 +249,6 @@
         'name': 'keyword.operator.logical.dart'
       }
       {
-        'match': ';'
-        'name': 'punctuation.terminator.dart'
-      }
-      {
         'match': '\\b(static|final|const)\\b'
         'name': 'storage.modifier.dart'
       }
@@ -356,4 +355,19 @@
         ]
       }
     ]
+  'punctuation':
+    'patterns': [
+      {
+        'match': ','
+        'name': 'punctuation.comma.dart'
+      }
+      {
+        'match': ';'
+        'name': 'punctuation.terminator.dart'
+      }
+      {
+        'match': '\\.'
+        'name': 'punctuation.dot.dart'
+      }
+    ]
 'scopeName': 'source.dart'


lowercasing things

lowercasing things

Resolves #11 and generally makes matching better.

--- src/ingress.coffee
+++ src/ingress.coffee
@@ -153,10 +153,10 @@
     msg.send lvls.join ""

   robot.respond /(I|@?\w+) (?:have|has|got|earned)(?: the)? :?([\w,\s]+):? badges?/i, (msg) ->
-    who = msg.match[1].replace '@', ''
-    badgeNames = (msg.match[2].replace /\s*/g, '').split ','
-
-    if who.toLowerCase() == 'i'
+    who = msg.match[1].toLowerCase().replace '@', ''
+    badgeNames = (msg.match[2].toLowerCase().replace /\s*/g, '').split ','
+
+    if who == 'i'
       who = msg.envelope.user
     else
       who = robot.brain.userForName who
@@ -202,10 +202,10 @@
       msg.reply "#{whowhat} no badges."

   robot.respond /(I|@?\w+) (?:do(?:n't|esn't| not)) have the :?(\w+):? badge/i, (msg) ->
-    who = msg.match[1].replace '@', ''
-    badgeName = msg.match[2]
-
-    if who.toLowerCase() == 'i'
+    who = msg.match[1].toLowerCase().replace '@', ''
+    badgeName = msg.match[2].toLowerCase()
+
+    if who == 'i'
       who = msg.envelope.user
     else
       who = robot.brain.userForName who


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/metered.coffee
+++ src/metered.coffee
@@ -13,6 +13,8 @@
   health: 500

 enemy.include Metered
+
+someOt

 player.meter 'health'
 # => Sets up a health meter that will be drawn during the player overlay event


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/metered.coffee
+++ src/metered.coffee
@@ -94,7 +94,26 @@
         stroke:
           color: borderColor
           width: 1.5
-
+
+###*
+  The position of this game object. By default it is the top left point.
+  Redefining the center method will change the relative position.
+
+

+  player = Core
+    x: 50
+    y: 40
+
+  player.include(Bounded)
+
+  player.position()
+  # => {x: 50, y: 40}
+

+
+  @name position
+  @methodOf Bounded#
+  @returns {Point} The position of this object
+  ###
   meter: (options={}) ->
     Object.reverseMerge options,
       borderColor: 'white'


NN now supports getInspectedObjects

NN now supports getInspectedObjects

--- src/neptune.coffee
+++ src/neptune.coffee
@@ -11,8 +11,10 @@
 # global == self == window (if in browser)
 if typeof global == 'object'
   # running in node.js
+  isNode = true
   global.self = global
 else
+  isNode = false
   self.global ||= self

 unless (->).name?
@@ -31,8 +33,19 @@
   @namespace: null
   @allNamespaces: {}
   @namespaces: []
-  @modules: []
-  @moduleNames: []
+  # @modules: []
+  # @moduleNames: []
+
+  @getName: ->
+    @_name || @name
+
+  @getInspectedObjects: ->
+    out = {}
+    for namespace in @namespaces
+      out[namespace.getName()] = namespace.getInspectedObjects()
+    for mod in @moduleNames
+      out[mod] = true
+    out

   # OUT: namespace
   @addNamespace: (name, namespace) ->
@@ -49,6 +62,7 @@

   @_setChildNamespace: (name, child) ->
     if typeof child == "function" && name.match /^[A-Z]/
+      child._name = name
       child.namespace = @
       child.namespacePath = @namespacePath + "." + name

@@ -64,7 +78,11 @@

   @addModules: (map) ->
     @modules = [] unless @hasOwnProperty "modules"
-    @moduleNames = [] unless @hasOwnProperty "moduleNames"
+    if @hasOwnProperty "moduleNames"
+      console.log("NeptuneNamespaces: alread have moduleNames for #{@getName()}")
+    else
+      console.log("NeptuneNamespaces: create moduleNames for #{@getName()}")
+      @moduleNames = []

     for name, module of map
       @moduleNames.push name
@@ -104,5 +122,8 @@
   @namespacePath: "Neptune"
   @namespace: null
   @isNamespace: (klass) -> klass?.prototype instanceof Base
+  @isNode: isNode
+  @package: _package = require "../package.json"
+  @version: _package.version

 console.log "neptune-namespaces global defined: self.Neptune"


Focus to domain input view on tab change

--- client/app/Applications/Environments.kdapplication/views/domains/domaincreationform.coffee
+++ client/app/Applications/Environments.kdapplication/views/domains/domaincreationform.coffee
@@ -31,8 +31,10 @@
         switch actionType
           when 'new'
             @tabs.showPaneByName 'NewDomain'
+            @newDomainEntryForm.inputs.domainName.setFocus()
           when 'subdomain'
             @tabs.showPaneByName 'SubDomain'
+            @subDomainEntryForm.inputs.domainName.setFocus()

     @addSubView @tabs = new KDTabView
       cssClass            : 'domain-tabs'
@@ -161,6 +163,7 @@
   viewAppended:->
     @updateDomains()
     KD.getSingleton("vmController").on 'VMListChanged', @bound 'updateDomains'
+    @subDomainEntryForm.inputs.domainName.setFocus()

 class CommonDomainCreationForm extends KDFormViewWithFields
   constructor:(options = {}, data)->


no load balancing, yet

no load balancing, yet

--- client/app/Applications/Environments.kdapplication/views/domains/domainsroutingview.coffee
+++ client/app/Applications/Environments.kdapplication/views/domains/domainsroutingview.coffee
@@ -147,7 +147,7 @@
   pistachio:->
     """

-    Click on any of your {{> @routingSelector}} to point and load balance to {{ #(domain)}}
+    Click on any of your {{> @routingSelector}} to point {{ #(domain)}}

     {{> @disconnectedVMs}}
     {{> @disconnectedKites}}


Fix bug with sabretooth loot

Fix bug with sabretooth loot

  Sabretooth tigres were dropping sabretooth which did
  not match item of name sabre_tooth

--- data/creatures/sabretooth.coffee
+++ data/creatures/sabretooth.coffee
@@ -15,11 +15,11 @@
   loot: (attacker, target, tile, weapon) ->
     if _.contains(attacker.skills, 'butchering')
       pelt: 1
-      sabretooth: 2
+      sabre_tooth: 2
       meat_raw: 10
     else
       pelt: 1
-      sabretooth: 2
+      sabre_tooth: 2
       meat_raw: 13

   is_habitable: (terrain, tile) ->


[koding_node_modules][kd-kite-datastore] removed extra space before arrow

--- node_modules_koding/kd-kite-datastore/lib/kd-kite-datastore/adapters/datastoreadapterfactory.coffee
+++ node_modules_koding/kd-kite-datastore/lib/kd-kite-datastore/adapters/datastoreadapterfactory.coffee
@@ -4,7 +4,7 @@

 module.exports = class KiteDataStoreAdapterFactory
   # default data store is mergen. (https://github.com/ybrs/mergen)
-  @create:(name="mergen", config, callback) ->
+  @create:(name="mergen", config, callback)->
     switch name
       when 'mergen' then callback new MergenAdapter config
       when 'dummy'  then callback new DummyAdapter config


Add cursor class if row is already selected

--- src/app/gutter.coffee
+++ src/app/gutter.coffee
@@ -21,11 +21,17 @@
   renderLineNumbers: (startScreenRow, endScreenRow) ->
     @firstScreenRow = startScreenRow
     lastScreenRow = -1
+    currentCursorRow = @cursorRow
     rows = @editor().bufferRowsForScreenRows(startScreenRow, endScreenRow)

     @lineNumbers[0].innerHTML = $$$ ->
       for row in rows
-        @div {class: 'line-number'}, if row == lastScreenRow then '•' else row + 1
+        rowClass = null
+        if row isnt currentCursorRow
+          rowClass = 'line-number'
+        else
+          rowClass = 'line-number cursor-line-number'
+        @div {class: rowClass}, if row == lastScreenRow then '•' else row + 1
         lastScreenRow = row

     @calculateWidth()


using @system.UID/GID for switching to make it possible to define from context config

--- platforms/node/lib/Platform.coffee
+++ platforms/node/lib/Platform.coffee
@@ -15,7 +15,7 @@
             settings.platform ?= 'node'
             settings.version = require(settings.libdir+'/package.json').version

-            ## platform hoistname
+            ## platform hostname
             settings.hostname = require('os').hostname()

             ## platform ident string
@@ -172,11 +172,11 @@
                 if process.getuid() is 0

                     ## chown tmpdir
-                    floyd.tools.files.chown @system.tmpdir, config.UID, config.GID
+                    floyd.tools.files.chown @system.tmpdir, @system.UID, @system.GID

                     ## chown process
-                    process.setgid(config.GID) # GID first ;-)
-                    process.setuid(config.UID)
+                    process.setgid(@system.GID) # GID first ;-)
+                    process.setuid(@system.UID)

                     ## EXPERIMENTAL! --> delete the require cache to prevent
                     ## unprivileged users from reading sensitive data
@@ -196,9 +196,9 @@

                     ## <-- EXPERIMENTAL

-                else if (config.UID && config.UID isnt process.getuid()) || (config.GID && config.GID isnt process.getgid())
+                else if (@system.UID && @system.UID isnt process.getuid()) || (@system.GID && @system.GID isnt process.getgid())
                     ctx.logger.warning 'WARNING: running unprivileged!'
-                    ctx.logger.warning '         changing UID/GID to %s/%s is impossible', (config.UID || config.GID), (config.GID || config.UID)
+                    ctx.logger.warning '         changing UID/GID to %s/%s is impossible', (@system.UID || @system.GID), (@system.GID || @system.UID)
                     ctx.logger.warning '         current UID/GID settings: %s/%s', process.getuid(), process.getgid()


Trigger 'window:close' command in the 'beforeunload' event handler.

When user wants to close the window, the 'beforeunload' event would be
called, then the closing would be cancelled and the 'window:close'
command would be triggered. In the 'window:close' handler, a confirm
dialog could be showed if there are unsaved contents, and if the window
is really meant to be closed, the window would be tried to be closed
again and this time 'beforeunload' handler wont't prevent it.

--- src/app/window.coffee
+++ src/app/window.coffee
@@ -110,6 +110,11 @@
   $(window).off('focus blur before')

 window.handleEvents = ->
+  $(window).on 'beforeunload', ->
+    unless windowIsClosing?
+      $(window).trigger 'window:close'
+      false
+
   $(window).command 'window:toggle-full-screen', => atom.toggleFullScreen()
   $(window).on 'focus', -> $("body").removeClass('is-blurred')
   $(window).on 'blur',  -> $("body").addClass('is-blurred')
@@ -271,7 +276,11 @@

 # Public: Shows a dialog asking if the window was _really_ meant to be closed.
 confirmClose = ->
+  close = ->
+    window.windowIsClosing = true
+    window.close()
+
   if rootView?
-    rootView.confirmClose().done -> window.close()
-  else
-    window.close()
+    rootView.confirmClose().done -> close()
+  else
+    close()


Fixed stupid disas output bug...

Fixed stupid disas output bug...

--- src/attributes.coffee
+++ src/attributes.coffee
@@ -63,8 +63,10 @@
       ln = bytes_array.get_uint 2
       @entries.push {'start_pc': spc,'line_number': ln}

-  disassemblyOutput: -> "  LineNumberTable:\n" +
-    "   line #{entry.line_number}: #{entry.start_pc}\n" for entry in @entries
+  disassemblyOutput: ->
+    rv = "  LineNumberTable:\n"
+    rv += "   line #{entry.line_number}: #{entry.start_pc}\n" for entry in @entries
+    rv

 class SourceFile
   name: 'SourceFile'


[feed] moved non-framework related functions to application level

--- core/KD.coffee
+++ core/KD.coffee
@@ -50,9 +50,6 @@
     log "we fail silently!", e

 @KD = $.extend (KD), do ->
-  # private member for tracking z-indexes
-  zIndexContexts  = {}
-
   create = (constructorName, options, data)->
     konstructor = @classes[constructorName] \
                 ? @classes["KD#{constructorName}"]
@@ -60,15 +57,6 @@

   create    : create
   new       : create
-
-  impersonate: (username)->
-    @remote.api.JAccount.impersonate username, (err)->
-      if err then new KDNotificationView title: err.message
-      else location.reload()
-
-  # testKDML:->
-  #   {KDMLParser} = Bongo.KDML
-  #   kdml = new KDMLParser @classes

   debugStates     : {}
   instances       : {}
@@ -82,84 +70,6 @@
   appClasses      : {}
   appScripts      : {}
   lastFuncCall    : null
-
-  nick:-> KD.whoami().profile.nickname
-
-  whoami:-> KD.getSingleton('mainController').userAccount
-
-  logout:->
-    mainController = KD.getSingleton('mainController')
-    delete mainController?.userAccount
-
-  isLoggedIn:-> @whoami() instanceof KD.remote.api.JAccount
-
-  isMine:(account)-> @whoami().profile.nickname is account.profile.nickname
-
-  checkFlag:(flagToCheck, account = KD.whoami())->
-    if account.globalFlags
-      if 'string' is typeof flagToCheck
-        return flagToCheck in account.globalFlags
-      else
-        for flag in flagToCheck
-          if flag in account.globalFlags
-            return yes
-    no
-
-  notifyError_:(message)->
-    console.log message
-    new KDNotificationView
-      type     : 'mini'
-      cssClass : 'error'
-      title    : message
-      duration : 3500
-
-  requireMembership:(options={})->
-
-    {callback, onFailMsg, onFail, silence, tryAgain, groupName} = options
-    unless KD.isLoggedIn()
-      # if there is fail message, display it
-      if onFailMsg
-        @notifyError_ onFailMsg
-
-      # if there is fail method, call it
-      onFail?()
-
-      # if login is a silent redirection
-      unless silence
-        @getSingleton('router').handleRoute "/Login", KD.config.entryPoint
-
-      # if there is callback and we want to try again
-      if callback? and tryAgain
-        unless KD.lastFuncCall
-          {mainController} = KD.singletons
-          mainController.once "accountChanged.to.loggedIn", =>
-            if groupName and KD.isLoggedIn()
-              @joinGroup_ groupName, (res)=>
-                unless res then return @notifyError_ "Joining to #{groupName} group failed"
-                KD.lastFuncCall?()
-                KD.lastFuncCall = null
-        KD.lastFuncCall = callback
-    else
-      if groupName
-        @joinGroup_ groupName, (res)=>
-          if res then callback?()
-          else @notifyError_ "Joining to #{groupName} group failed 2"
-      else callback?()
-
-  joinGroup_:(groupName, callback)->
-    unless groupName then return callback true
-    user = @whoami()
-    user.fetchGroups (err, groups)=>
-      if err or !groups then return callback false
-      @remote.api.JGroup.one { slug: groupName }, (err, currentGroup)=>
-        if err then return @notifyError_ err.message
-        for group in groups
-          if groupName is group.group.slug
-            return callback true
-        currentGroup.join (err)=>
-          if err then return callback false
-          @notifyError_ "Joined to #{groupName} group!"
-          return callback true

   socketConnected:->
     @backendIsConnected = yes
@@ -182,6 +92,10 @@
   deleteInstance:(anInstanceId)->
     @unregisterInstance anInstanceId
     # anInstance = null #FIXME: Redundant? See unregisterInstance
+
+  extend:(functions)->
+    for methodName, method of functions
+      @[methodName] = method

   registerSingleton:(singletonName,object,override = no)->
     if (existingSingleton = KD.singletons[singletonName])?
@@ -251,30 +165,6 @@
   getKDViewInstanceFromDomElement:(domElement)->
     @instances[$(domElement).data("data-id")]

-  # Get next highest Z-index
-  getNextHighestZIndex:(context)->
-   uniqid = context.data 'data-id'
-   if isNaN zIndexContexts[uniqid]
-     zIndexContexts[uniqid] = 0
-   else
-     zIndexContexts[uniqid]++
-
-  jsonhTest:->
-    method    = 'fetchQuestionTeasers'
-    testData  = {
-      foo: 10
-      bar: 11
-    }
-
-    start = Date.now()
-    $.ajax "/#{method}.jsonh",
-      data     : testData
-      dataType : 'jsonp'
-      success : (data)->
-        inflated = JSONH.unpack data
-        KD.log 'success', inflated
-        KD.log Date.now()-start
-
   enableLogs:do->
     oldConsole = window.console
     window.console = {}


default to populate file attachment metadata in msg.$fetch

--- www/js/model.coffee
+++ www/js/model.coffee
@@ -209,9 +209,9 @@
 			@msgType: (msg) ->
 				if msg.file
 					switch true
-						when sails.services.file.isImg(msg.file.base)
+						when sails.services.file.isImg msg.file_inode
 							return 'img'
-						when sails.services.file.isAudio(msg.file.base)
+						when sails.services.file.isAudio msg.file_inode
 							return 'audio'
 						else
 							return 'file'
@@ -230,6 +230,9 @@
 					ret[field] = new Date Date.parse ret[field]

 				return ret
+
+			$fetch: (opts) ->
+				super _.extend opts, populate: ['file_inode', 'createdBy']

 		class Attachment extends pageableAR.Model
 			$urlRoot: ->
@@ -290,6 +293,9 @@

 			model: Msg

+			$fetch: (opts) ->
+				super _.extend opts, populate: ['file_inode', 'createdBy']
+
 		class Device extends pageableAR.Model
 			$urlRoot: ->
 				urlRoot(@, "api/device", env.server.mobile.urlRoot)


Handle multiple legacy gadgets

Handle multiple legacy gadgets

--- src/preview.coffee
+++ src/preview.coffee
@@ -24,23 +24,25 @@

   async.map dirs, linkManifestDir.bind(this, app), (err, manifests) ->
     if err then return callback err
-
-    coursePath = path.join(__dirname, '../templates/course.json')
-    fs.readJson coursePath, (err, course) ->
+    async.map dirs, linkLegacyDir.bind(this, app), (err) ->
       if err then return callback err

-      # Inject course palette
-      course.palette = manifests
-      course.isEditable = true
+      coursePath = path.join(__dirname, '../templates/course.json')
+      fs.readJson coursePath, (err, course) ->
+        if err then return callback err

-      app.use('/api', api({ manifests, course, assets: [], representations: {} }))
-        .use('/components', express.static(path.join(__dirname, '../node_modules')))
-        .use(express.static(launchPath))
-        .use(express.static(path.join(__dirname, '../html')))
-        .use(express.logger())
+        # Inject course palette
+        course.palette = manifests
+        course.isEditable = true

-      if options.port then app.listen options.port
-      callback null, manifests
+        app.use('/api', api({ manifests, course, assets: [], representations: {} }))
+          .use('/components', express.static(path.join(__dirname, '../node_modules')))
+          .use(express.static(launchPath))
+          .use(express.static(path.join(__dirname, '../html')))
+          .use(express.logger())
+
+        if options.port then app.listen options.port
+        callback null, manifests

 linkManifestDir = (app, dir, callback) ->
   manifest.readManifest dir, (err, json) ->
@@ -55,6 +57,10 @@

     callback null, man

+linkLegacyDir = (app, dir, callback) ->
+  app.use '/scripts', express.static(path.resolve dir)
+  callback null
+
 mapManifest = (manifest) ->
   manifest.id = shortid.generate()
   manifest.catalog = 'local'


Updated for template and render conventions

--- rest_controller.coffee
+++ rest_controller.coffee
@@ -9,7 +9,7 @@
   constructor: (app, options={}) ->
     @[key] = value for key, value of options
     @white_lists or= {}
-    @views or= {}
+    @templates or= {}

     if @auth
       app.get "#{@route}/:id", @auth, @show
@@ -131,12 +131,12 @@
       res.status(500).send(error: err.toString())

   render: (req, json, callback) ->
-    view_name = req.query.$view or @default_view
-    return callback(null, json) unless view_name
-    return callback(new Error "Unrecognized view: #{view_name}") unless view = @views[view_name]
+    template_name = req.query.$render or req.query.$template or @default_template
+    return callback(null, json) unless template_name
+    return callback(new Error "Unrecognized template: #{template_name}") unless template = @templates[template_name]

-    options = (if @viewOptions then @viewOptions(req, view_name) else {})
+    options = (if @templateOptions then @templateOptions(req, template_name) else {})
     if _.isArray(json)
-      JSONUtils.renderModelsJSON _.map(json, (model_json) => new @model_type(@model_type::parse(model_json))), view, options, callback
+      JSONUtils.renderModelsJSON _.map(json, (model_json) => new @model_type(@model_type::parse(model_json))), template, options, callback
     else
-      JSONUtils.renderModelJSON new @model_type(@model_type::parse(json)), view, options, callback
+      JSONUtils.renderModelJSON new @model_type(@model_type::parse(json)), template, options, callback


Remove debug logs

Remove debug logs

--- app/src/storage/synced_store.coffee
+++ app/src/storage/synced_store.coffee
@@ -179,8 +179,6 @@
           throw Errors.NoChanges
       # Create commit hash
       [commitHash, pushedData] = @_computeCommit(data, @_changes)
-      l "DATA", data
-      l "PUSHED DATA", pushedData
       # Jsonify data
       @_encryptToJson(pushedData)
     .then (data) => if hasRemoteData then @client.put_settings(data) else @client.post_settings(data)
@@ -188,7 +186,6 @@
       @_setLastMd5(md5)
       # Merge changes into store
       @_clearChanges()
-      l "PUSHED DATA"
       @_setAllData(pushedData)
     .then () => @emit 'pushed', this
     .fail (e) =>
@@ -211,7 +208,6 @@

   _computeCommit: (data, changes) ->
     data = @_applyChanges(data, changes)
-    l "APPLY CHANGES ", changes, data
     commitHash = ledger.crypto.SHA256.hashString _(data).toJson()
     data.__hashes = [commitHash].concat(data.__hashes or [])
     [commitHash, data]


name menu item Regard

name menu item Regard

--- menus/regard-analytics.cson
+++ menus/regard-analytics.cson
@@ -7,7 +7,7 @@
   {
     'label': 'Packages'
     'submenu': [
-      'label': 'regard-analytics'
+      'label': 'Regard'
       'submenu': [
         { 'label': 'Toggle', 'command': 'regard-analytics:toggle'}
         { 'label': 'My data', 'command': 'regard-analytics:my-data' }


Adds toggle attribute to main parent

Adds toggle attribute to main parent

--- app/assets/javascripts/backbone/views/_base/itemview.js.coffee
+++ app/assets/javascripts/backbone/views/_base/itemview.js.coffee
@@ -9,11 +9,32 @@
     orignalEvents:
       'mouseenter'         : 'showOverlay'
       'mouseleave'         : 'hideOverlay'
-
+      'click .watched-btn' : 'toggleWatched'
+      'click .queued-btn'  : 'toggleQueued'
+      'click .trashed-btn' : 'toggleTrashed'
+
     showOverlay: ->
       this.$el.find('.overlay').fadeIn(500)

     hideOverlay: ->
       this.$el.find('.overlay').fadeOut(500)

+    toggleWatched: ->
+      if this.model.get('watched') is true
+        this.model.set(watched: false).save()
+      else
+        this.model.set(watched: true).save()
+
+    toggleQueued: ->
+      if this.model.get('queued') is true
+        this.model.set(queued: false).save()
+      else
+        this.model.set(queued: true).save()

+    toggleTrashed: ->
+      if this.model.get('trashed') is true
+        this.model.set(trashed: false).save()
+      else
+        this.model.set(trashed: true).save()
+
+


Changed the "posts" query to search for a tag

Current implementation only grabs direct children of the
`posts` directory which breaks when you add sub-folders.

Updated implementation to avoid this problem and so behaviour
matches comment directly above...

--- docpad.coffee
+++ docpad.coffee
@@ -77,7 +77,7 @@

 		# This one, will fetch in all documents that have the tag "post" specified in their meta data
 		posts: (database) ->
-			database.findAllLive({relativeOutDirPath:'posts'},[date:-1])
+			database.findAllLive({tags: $has: ['post']}}, [date:-1])

 	# =================================


Collections in config file was over-indented.

--- docpad.coffee
+++ docpad.coffee
@@ -1,13 +1,15 @@
 # Define the Configuration
 docpadConfig = {
+
+	collections:
+		pages: ->
+			@getCollection("html").findAllLive({isPage:true})
+		posts: ->
+			@getCollection('html').findAllLive({relativeOutDirPath: 'posts'})
+
 	templateData:
 		site:
 			title: "Curly Hair Coder"
-
-		getPreparedTitle: -> if @document.title then "#{@document.title} | #{@site.title}" else @site.title
-		collections:
-			pages: ->
-				@getCollection("html").findAllLive({isPage:true})
 }

 # Export the Configuration


rework ChartView#update  * move(translate) datapoint which contain the circle or whatever representation of the data

--- app/views/chart/simple-graph.coffee
+++ app/views/chart/simple-graph.coffee
@@ -186,25 +186,43 @@
     @plot.call(@zoom)
     @update();

+  dataRenderStage: null
+
   update: () =>
+    @dataRenderStage = null
     lines = @vis.select("path").attr("d", @line(@points));

-    circle = @vis.select("svg").selectAll("circle")
+    circle = @vis.select("svg").selectAll(".datapoint")
         .data(@points)

-    circle.enter().append("circle")
-        .attr("class", (d) => if d is @selected then "selected" else null )
-        .attr("cx",    (d) => @x(d.x) )
-        .attr("cy",    (d) => @y(d.y) )
+    dataPoint = circle.enter().append("g")
+      .attr("class", "datapoint")
+      .attr("transform", (d, i) => "translate(#{@x(d.x)},#{@y(d.y)})")
+
+    # circle.enter().append("circle")
+    dataPoint.append("circle")
+        .attr("class", (d) =>
+          if @dataRenderStage isnt "ENTERING"
+            @dataRenderStage = "ENTERING"
+            console.log "ENTERING: start"
+          if d is @selected then "selected" else null )
+        .attr("cx", 0.0 )
+        .attr("cy", 0.0 )
         .attr("r", 6.0)
         .style("cursor", "ns-resize")
         .on("mousedown.drag",  @datapointDrag)
         .on("touchstart.drag", @datapointDrag)

     circle
-        .attr("class", (d) => if d is @selected then "selected" else null )
-        .attr("cx",    (d) => @x(d.x) )
-        .attr("cy",    (d) => @y(d.y) )
+      .attr("transform", (d, i) => "translate(#{@x(d.x)},#{@y(d.y)})")
+    # circle
+    #     .attr("class", (d) =>
+    #       if @dataRenderStage isnt "UPDATING"
+    #         @dataRenderStage = "UPDATING"
+    #         console.log "UPDATING: start"
+    #       if d is @selected then "selected" else null )
+    #     .attr("cx",    (d) => @x(d.x) )
+    #     .attr("cy",    (d) => @y(d.y) )

     circle.exit().remove();


reticulating sprites

reticulating sprites

--- coffee/main.coffee
+++ coffee/main.coffee
@@ -405,14 +405,13 @@
       @args = []

     setIcon: (x=0, y=0, z=50) =>
-      material = new THREE.SpriteMaterial({
-        map: @tex,
-        #alphaTest: 0.5,
-        depthTest: false,
-        depthWrite: false
-      })
+      if @parent? and @shp?
+        @parent.obj3d.remove(@shp.obj3d)
       @shp = new Shapes.Icon(@tex, x, y, z)
       @shp.obj3d.userData = this
+      if @parent?
+        @parent.obj3d.add(@shp.obj3d)
+      g.ve.render()

     addArgs: () ->
       _args = @model.props.params
@@ -1581,7 +1580,17 @@

       if m.props.icon != ''
         @ve.loadIcon(m.props.name, (tex) =>
-          m.setIcon(@ve.iconCache[m.props.name])
+          tex = @ve.iconCache[m.props.name]
+          _tex = tex.clone()
+          _tex.needsUpdate = true
+          m.setIcon(tex)
+          for x in m.instances
+            x.tex = tex.clone()
+            x.tex.needsUpdate = true
+            x.setIcon(
+              x.shp.obj3d.position.x,
+              x.shp.obj3d.position.y
+            )
         )
         true

@@ -1590,6 +1599,8 @@

   doLoad: (m) =>
     @loadModels(m.models)
+    #while(@latchup > @latchdown)
+    #  console.log(@latchdown)
     @loadElements(m.elements)
     @loadSimSettings(m.simSettings)
     true
@@ -1609,11 +1620,11 @@
     true

   loadPhyo: (x) =>
+    m = loadedModels[x.model]
     p = new BaseElements.Phyo(@ve.surface.baseRect,
                                x.position.x, x.position.y, x.position.z)
     @setProps(p, x)
     @ve.surface.elements.push(p)
-    m = loadedModels[p.props.model]
     m.instances.push(p)
     p.model = m
     p.loadArgValues()


cleanup

cleanup


Update resource.coffee

Update resource.coffee

Fix

https://github.com/Shopfrogs/Nodify/pull/8

--- src/resource.coffee
+++ src/resource.coffee
@@ -14,6 +14,8 @@
       method: method
       json: slug isnt 'oauth'
       headers:if @oauth is yes and @oauth_token? then {'X-Shopify-Access-Token':@oauth_token} else {}
+
+    options.headers['Content-Type'] = 'application/x-www-form-urlencoded' if method is "POST"

     if fields?
       params = {}


:fire: Remove dead code

:fire: Remove dead code

--- src/class-page.coffee
+++ src/class-page.coffee
@@ -100,28 +100,3 @@
   parameters: (method) ->
     names = (name for {name} in method.arguments)
     names.join(', ')
-
-
-
-
-  instanceMethodDetails: (method) ->
-    method.signature = @signature(method)
-    method.description = @markdownify(method.description)
-    method.parameterBlock = if method.arguments then @parameterBlock(method) else ''
-    method.returnValueBlock = if method.returnValues then @returnValueBlock(method) else ''
-    Template.render('instance-method-details', method)
-
-  instanceMethodDetailsSection: ->
-    methods = (@instanceMethodDetails(method) for method in @object.instanceMethods)
-    if methods?.length > 0
-      Template.render('instance-method-detail-section', content: methods.join('\n'))
-
-  instanceMethodSummary: (method) ->
-    method.signature = @signature(method)
-    method.summary = @markdownify(method.summary)
-    Template.render('instance-method-summary', method)
-
-  instanceMethodSummarySection: ->
-    methods = (@instanceMethodSummary(method) for method in @object.instanceMethods)
-    if methods?.length > 0
-      Template.render('instance-method-summary-section', content: methods.join('\n'))


Redirect logs to stderr using threshold level 'error'.

--- src/coffee/run.coffee
+++ src/coffee/run.coffee
@@ -295,7 +295,7 @@
         logConfig:
           name: "#{package_json.name}-#{package_json.version}"
           streams: [
-            {level: 'info', stream: process.stderr}
+            {level: 'error', stream: process.stderr}
             {level: opts.parent.logLevel, path: "#{opts.parent.logDir}/sphere-brickfox-connector.log"}
           ]
           src: if opts.parent.bunyanVerbose then true else false
@@ -460,4 +460,4 @@
     program.parse argv
     program.help() if program.args.length is 0

-module.exports.run process.argv+module.exports.run process.argv


Q.spread calls 'all' intially, so skip it.

--- src/coffee/run.coffee
+++ src/coffee/run.coffee
@@ -22,9 +22,7 @@
     deferred.reject(new Error(error))
   deferred.promise

-promises = Q.all [readCsvPromise(argv.types), readCsvPromise(argv.attributes)]
-
-Q.spread promises, (types, attributes) ->
+Q.spread [readCsvPromise(argv.types), readCsvPromise(argv.attributes)], (types, attributes)->
   generator = new ProductTypeGenerator
   generator.run types, attributes, (success) ->
     process.exit 1 unless success


Fixes display text for profile specfic auto-complete

--- models/search_result.coffee
+++ models/search_result.coffee
@@ -20,7 +20,7 @@
     @value = @display()

   display: ->
-    @get('name') || @trimmedDisplay()
+    _.trim(@get('name') || @get('owner')?.name || @get('display'))

   trimmedDisplay: ->
     _.trim(_.truncate(@get('display'), 75))


remove useless log

remove useless log

--- src/service.coffee
+++ src/service.coffee
@@ -62,8 +62,16 @@
         @events.emit event, args...

     send:(msg, cb) ->
-
-    onRecieve:(cb) ->
+        to = msg.to
+        if to?.type is 'user'
+            @sendToFriend(msg, cb)
+            return
+        if to?.type is 'group'
+            @sendToGroup(msg, cb)
+            return
+        if to?.type is 'dgroup'
+            @sendToDiscussionGroup(msg, cb)
+            return

     friendInfo:(cb) =>
         params =
@@ -77,7 +85,7 @@
             .query(params)
             .header('Cookie', @cookie())
             .get()((err, resp, body) =>
-                cb body
+                cb err, body
         )

     # updateFriends:() ->
@@ -183,7 +191,6 @@
                 return x.uin

     sendToFriend: (msg, callback) ->
-        console.log 'send to friend'
         if not msg.to
             console.log 'no to'
             return
@@ -203,7 +210,6 @@
             psessionid: @authInfo.psessionid
             content: msg.message()

-        console.log rValue
         params =
             r: JSON.stringify rValue
             clientid: @authInfo.clientid
@@ -215,8 +221,7 @@
             .header('Cookie', @cookie())
             .header('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8')
             .post(QueryString.stringify(params))((err, resp, body) ->
-                console.log 'send friend message', err, body
-                callback && callback body
+                callback && callback err, body
             )

     sendToGroup: (msg, callback) ->
@@ -243,7 +248,7 @@
             .header('Cookie', @cookie())
             .header('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8')
             .post(QueryString.stringify(params))((err, resp, body) ->
-                console.log 'send group message', err, body
+                callback && callback err, body
             )

     sendToDiscussionGroup: (msg, callback) ->
@@ -271,7 +276,7 @@
             .header('Cookie', @cookie())
             .header('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8')
             .post(QueryString.stringify(params))((err, resp, body) ->
-                console.log 'send discussion group message', err, body
+                callback && callback err, body
             )

     online: (callback)->
@@ -302,7 +307,6 @@

                 ret = JSON.parse(body)
                 if ret.retcode is 0
-                    console.log 'success'
                     @authInfo.psessionid = ret.result.psessionid
                     @authInfo.uin = ret.result.uin
                     @authInfo.vfwebqq = ret.result.vfwebqq
@@ -313,7 +317,6 @@
     # discussionGroupMember: ->

     poll: ->
-        console.log "polling..."
         rValue =
             clientid: @authInfo.clientid
             psessionid: @authInfo.psessionid
@@ -329,7 +332,7 @@
             .header('Cookie', @cookie())
             .header('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8')
             .post(QueryString.stringify(params))((err, resp, body) =>
-                console.log 'poll return', body
+                # console.log 'poll return', body
                 @emit 'poll', err, body
         )

@@ -339,6 +342,7 @@
         for message in data
             m = Message.parse(message)
             console.log m
+        @emit 'message', m

     logout: ->
         @stop()
@@ -383,8 +387,16 @@
             , 1000*60
             )

-            @friendInfo((data)->
-                console.log 'friendInfo', data
+            @emit 'ready'
+
+            @friendInfo((err, data)=>
+                if err isnt null
+                    @emit 'error', err
+                    return
+                ret = JSON.parse(data)
+                if ret.retcode isnt 0
+                    return
+                @info = ret.result
             )
             @friendList((err, data)=>
                 if err isnt null
@@ -394,7 +406,6 @@
                 if ret.retcode isnt 0
                     return
                 @friends = Info.parseFriends(ret.result)
-                console.log 'friendList', @friends
             )
             @groupList((err, data)=>
                 if err isnt null
@@ -404,7 +415,6 @@
                 if ret.retcode isnt 0
                     return
                 @groups = Info.parseGroups(ret.result)
-                console.log 'groupList', @groups
             )
             @discussionGroupList((err, data)=>
                 if err isnt null
@@ -414,7 +424,6 @@
                 if ret.retcode isnt 0
                     return
                 @dgroups = Info.parseDisscussGroups(ret.result)
-                console.log 'discussionGroupList', @dgroups
             )
             # @groupMember('', (data)->
             #     console.log 'groupMember',data


Fix types in models

Fix types in models

--- assets/javascripts/models.js.coffee
+++ assets/javascripts/models.js.coffee
@@ -17,7 +17,7 @@
 App.RoomUserState = DS.Model.extend
   user_id: DS.attr("number")
   joined: DS.attr("boolean")
-  last_pinged_at: DS.attr("datetime")
+  last_pinged_at: DS.attr("date")
   room: DS.belongsTo("room")

@@ -26,3 +26,4 @@
   type:   DS.attr("string")
   roomId: DS.attr("string")
   userId: DS.attr("string")
+  created_at: DS.attr("date")


Clean up text input code to magically fix error-throwing code

--- src/controller.coffee
+++ src/controller.coffee
@@ -1369,7 +1369,7 @@

     # We also need to initialise some fields
     # for knowing what is focused
-    @socketFocus = null
+    @textFocus = null
     @textFocus = null
     @textInputAnchor = null

@@ -1500,12 +1500,12 @@

     # If there is already a focus, we
     # need to wrap some things up with it.
-    if @socketFocus? and @socketFocus isnt focus
+    if @textFocus? and @textFocus isnt focus

       # The first of these is an undo operation;
       # we need to add this text change to the undo stack.
       @addMicroUndoOperation 'CAPTURE_POINT'
-      @addMicroUndoOperation new TextChangeOperation @socketFocus, @oldFocusValue
+      @addMicroUndoOperation new TextChangeOperation @textFocus, @oldFocusValue
       @oldFocusValue = null

       # The second of these is a reparse attempt.
@@ -1513,7 +1513,7 @@
       # value.
       try
         # TODO make 'reparsable' property, bubble up until then
-        parseParent = @socketFocus.parent
+        parseParent = @textFocus.parent

         newParse = coffee.parse(parseParent.stringify(), wrapAtRoot: false)

@@ -1537,17 +1537,14 @@
           throw new Error 'Socket is split.'

       catch
-        @extraMarks[@socketFocus.id] =
-          model: @socketFocus
+        @extraMarks[@textFocus.id] =
+          model: @textFocus
           style: {color: '#F00'}

         @redrawMain()

     # Now we're done with the old focus,
     # we can start over.
-    #
-    # Literally set the focus.
-    @socketFocus = focus

     # If we're _unfocusing_, just do so.
     if not focus?
@@ -1932,8 +1929,7 @@
     # If the destination is not inside the tree,
     # abort.
     unless destination? then return
-    head = destination; until head in [null, @tree.end] then head = head.next
-    unless head? then return
+    unless @inTree(destination) then return

     # Otherwise, splice the cursor out.
     @cursor.remove()
@@ -2030,7 +2026,7 @@

   hook 'key.tab', 0, ->
     if @shiftKeyPressed
-      if @socketFocus? then head = @socketFocus.start
+      if @textFocus? then head = @textFocus.start
       else head = @cursor

       until (not head?) or head.type is 'socketEnd' and head.container.start.next.type is 'text'
@@ -2040,7 +2036,7 @@
       return false

     else
-      if @socketFocus? then head = @socketFocus.end
+      if @textFocus? then head = @textFocus.end
       else head = @cursor

       until (not head?) or head.type is 'socketStart' and head.container.start.next.type is 'text'
@@ -2073,7 +2069,7 @@
     # sessions. We will, however, delete a handwritten
     # block if it is currently empty.
     if not @textFocus? or
-        (@hiddenInput.value.length is 0 and @socketFocus.handwritten)
+        (@hiddenInput.value.length is 0 and @textFocus.handwritten)
       @deleteAtCursor()
       state.capturedBackspace = true
       return false
@@ -2242,11 +2238,11 @@
   # If we press tab while we are editing
   # a handwritten block, we create and indent.
   hook 'key.tab', 0, ->
-    if @socketFocus? and @socketFocus.handwritten
+    if @textFocus? and @textFocus.handwritten
       @addMicroUndoOperation 'CAPTURE_POINT'

       # Seek the block directly before this
-      head = @socketFocus.start
+      head = @textFocus.start
       until head.type is 'blockEnd'
         head = head.prev

@@ -2269,14 +2265,14 @@

       # Go through the motions of moving this block into
       # the indent we have just found.
-      @addMicroUndoOperation new PickUpOperation @socketFocus.start.prev.container
-      @socketFocus.start.prev.container.spliceOut() #MUTATION
-
-      @addMicroUndoOperation new DropOperation @socketFocus.start.prev.container, head
-      @socketFocus.start.prev.container.spliceIn head #MUTATION
+      @addMicroUndoOperation new PickUpOperation @textFocus.start.prev.container
+      @textFocus.start.prev.container.spliceOut() #MUTATION
+
+      @addMicroUndoOperation new DropOperation @textFocus.start.prev.container, head
+      @textFocus.start.prev.container.spliceIn head #MUTATION

       # Move the cursor up to where the block now is.
-      @moveCursorTo @socketFocus.start.prev.container.end
+      @moveCursorTo @textFocus.start.prev.container.end

       @redrawMain()

@@ -2286,7 +2282,7 @@
   hook 'key.backspace', 0, (state) ->
     if state.capturedBackspace then return

-    if  not @socketFocus? and
+    if  not @textFocus? and
         @cursor.prev?.prev?.type is 'indentStart' and
         (indent = @cursor.prev.prev.indent).stringify().trim().length is 0

@@ -2448,6 +2444,7 @@
       @aceEditor.resize true

       @redrawMain noText: true
+      @textFocus = @lassoAnchor = null

       @currentlyUsingBlocks = false; @currentlyAnimating = true

@@ -2577,10 +2574,8 @@
         return setValueResult

       if @aceEditor.getFirstVisibleRow() is 0
-        console.log 'is 0'
         @mainScroller.scrollTop = 0
       else
-        console.log 'scrolling to line', @aceEditor.getFirstVisibleRow()
         @mainScroller.scrollTop = @view.getViewNodeFor(@tree).bounds[@aceEditor.getFirstVisibleRow()].y

       setTimeout (=>
@@ -2670,21 +2665,17 @@

         for el in [@paletteWrapper, @mainCanvas, @highlightCanvas]
           el.style.opacity = 0
-          el.style.transform = "opacity #{fadeTime}ms linear"

         setTimeout (=>
-          @paletteWrapper.style.opacity =
-          @mainCanvas.style.opacity =
-          @highlightCanvas.style.opacity = 1
+          for el in [@paletteWrapper, @mainCanvas, @highlightCanvas]
+            el.style.transition = "opacity #{fadeTime}ms linear"
+            el.style.opacity = 1
         ), translateTime

         @iceElement.style.transition = "left #{translateTime}ms"
         @iceElement.style.left = "#{@paletteWrapper.offsetWidth}px"

         setTimeout (=>
-          @paletteWrapper.className.replace /\ ice-fade-in/, ''
-          @mainCanvas.className.replace /\ ice-fade-in/, ''
-          @highlightCanvas.className.replace /\ ice-fade-in/, ''
           @iceElement.style.transition = ''

           @currentlyAnimating = false
@@ -3335,8 +3326,6 @@

     testPartner.style.verticalAlign = 'text-bottom'
     offsetBottom = testPartner.offsetTop - testElement.offsetTop
-
-    console.log testWrapper

     #document.body.removeChild testWrapper

@@ -3399,7 +3388,6 @@

   getFontHeight = (family, size) ->
     metrics = fontMetrics family, size
-    console.log metrics
     return metrics.descent - metrics.ascent

   # DEBUG CODE


Add bubbling for reparses, and improve error handling for reparsing.

--- src/controller.coffee
+++ src/controller.coffee
@@ -1004,8 +1004,8 @@

         # Substitute in expansion for this palette entry, if supplied.
         expansion = @clickedBlockPaletteEntry.expansion
-        if 'function' is typeof expansion then expansion = expansion();
-        if (expansion) then expansion = parseBlock(@mode, expansion);
+        if 'function' is typeof expansion then expansion = expansion()
+        if (expansion) then expansion = parseBlock(@mode, expansion)
         @draggingBlock = (expansion or @draggingBlock).clone()

       else
@@ -1293,7 +1293,12 @@
         # Now that we've done that, we can annul stuff.
         @endDrag()

-  Editor::reparseRawReplace = (oldBlock) ->
+  Editor::reparseRawReplace = (oldBlock, originalTrigger = oldBlock) ->
+    # Get the parent in case we need to bubble
+    # up later
+    parent = oldBlock.visParent()
+
+    # Attempt to parse the block we are given out-of-context
     try
       newParse = @mode.parse(oldBlock.stringify(@mode), wrapAtRoot: true)
       newBlock = newParse.start.next.container
@@ -1309,8 +1314,15 @@
           newBlock.rawReplace oldBlock

     catch e
-      throw e
-      return false
+      # Attempt to bubble up the reparse, passing along
+      # the original block that triggered the reparse.
+      if parent?
+        return @reparseRawReplace parent, originalTrigger
+      else
+        # Mark the original triggering block as having caused
+        # an error.
+        @markBlock originalTrigger, {color: '#F00'}
+        return false

   Editor::findForReal = (token) ->
     head = @tree.start; i = 0
@@ -1931,8 +1943,32 @@
         cursorPosition = @getRecoverableCursorPosition()

       # The second of these is a reparse attempt.
+      #
       # If we can, try to reparse the focus
       # value.
+      #
+      # When reparsing occurs, we first try to treat the socket
+      # as a separate block (inserting parentheses, etc), then fall
+      # back on reparsing it with original text before giving up.
+      #
+      # For instance:
+      #
+      # (a * b)
+      #   -> edits [b] to [b + c]
+      #   -> reparse to b + c
+      #   -> inserts with parens to (a * (b + c))
+      #   -> finished.
+      #
+      # OR
+      #
+      # function (a) {}
+      #   -> edits [a] to [a, b]
+      #   -> reparse to a, b
+      #   -> inserts with parens to function((a, b)) {}
+      #   -> FAILS.
+      #   -> Fall back to raw reparsing the parent with unparenthesized text
+      #   -> Reparses function(a, b) {} with two paremeters.
+      #   -> Finsihed.
       unless @textFocus.handwritten
         newParse = null
         string = @textFocus.stringify(@mode).trim()
@@ -1956,16 +1992,15 @@
           @addMicroUndoOperation new TextReparseOperation @textFocus, unparsedValue
           shouldPop = true

-      # TODO make 'reparsable' property, bubble up until then
+      # See if the parent is still parseable
       unless @reparseRawReplace @textFocus.parent
-        # If we can't reparse the parent, abort all reparses
+        # If it is not, revert to the original text
         @populateSocket @textFocus, originalText
-
         if shouldPop then @undoStack.pop()

-        #@extraMarks[@textFocus.id] =
-        #  model: @textFocus
-        #  style: {color: '#F00'}
+        # Attempt to reparse the parent again with
+        # the original text; otherwise fail.
+        @reparseRawReplace @textFocus.parent

         @redrawMain()

@@ -2637,13 +2672,12 @@

       if head.type is 'socketStart' and
           (head.next.type is 'text' or head.next is head.container.end)
-        # Avoid problems with reparses
-        if @textFocus? and head.container.hasParent @textFocus.parent
-          persistentParent = @textFocus.getCommonParent(head.container).parent
-
-          chars = getCharactersTo persistentParent, head.container.start
+        # Avoid problems with reparses by getting text offset location
+        # of the given socket before reparsing and recovering it afterward.
+        if @textFocus?
+          chars = @getCharactersTo head.container.start
           @setTextInputFocus null
-          socket = getSocketAtChar persistentParent, chars
+          socket = @getSocketAtChar chars
         else
           socket = head.container
           @setTextInputFocus null
@@ -2714,18 +2748,18 @@
     @setTextInputFocus null
     @scrollCursorIntoPosition()

-  getCharactersTo = (parent, token) ->
+  Editor::getCharactersTo = (token) ->
     head = token
     chars = 0

-    until head is parent.start
+    until head is @tree.start
       if head.type is 'text' then chars += head.value.length
       head = head.prev

     return chars

-  getSocketAtChar = (parent, chars) ->
-    head = parent.start
+  Editor::getSocketAtChar = (chars) ->
+    head = @tree.start
     charsCounted = 0

     until charsCounted >= chars and head.type is 'socketStart' and
@@ -2747,12 +2781,12 @@
         head = head.prev

       if head?
-        if @textFocus? and head.container.hasParent @textFocus.parent
-          persistentParent = @textFocus.getCommonParent(head.container).parent
-
-          chars = getCharactersTo persistentParent, head.container.start
+        # Avoid problems with reparses by getting text offset location
+        # of the given socket before reparsing and recovering it afterward.
+        if @textFocus?
+          chars = @getCharactersTo head.container.start
           @setTextInputFocus null
-          socket = getSocketAtChar persistentParent, chars
+          socket = @getSocketAtChar chars
         else
           socket = head.container
           @setTextInputFocus null
@@ -2768,12 +2802,12 @@
           (head.container.start.next.type is 'text' or head.container.start.next is head.container.end)
         head = head.next
       if head?
-        if @textFocus? and head.container.hasParent @textFocus.parent
-          persistentParent = @textFocus.getCommonParent(head.container).parent
-
-          chars = getCharactersTo persistentParent, head.container.start
+        # Avoid problems with reparses by getting text offset location
+        # of the given socket before reparsing and recovering it afterward.
+        if @textFocus?
+          chars = @getCharactersTo head.container.start
           @setTextInputFocus null
-          socket = getSocketAtChar persistentParent, chars
+          socket = @getSocketAtChar chars
         else
           socket = head.container
           @setTextInputFocus null
@@ -3633,6 +3667,16 @@

     @redrawHighlights()

+  Editor::markBlock = (block, style) ->
+    key = @nextMarkedBlockId++
+
+    @markedBlocks[key] = {
+      model: block
+      style: style
+    }
+
+    return key
+
   # ## Mark
   # `mark(line, col, style)` will mark the first block after the given (line, col) coordinate
   # with the given style.


Added extra check for some URLs.

Added extra check for some URLs.

--- fetsy-hammertag/scripts/app.coffee
+++ fetsy-hammertag/scripts/app.coffee
@@ -33,6 +33,16 @@
         # For any unmatched url, redirect to /
         $urlRouterProvider.otherwise '/'

+        permissionDeniedCheck = [
+            '$state'
+            '$rootScope'
+            ($state, $rootScope) ->
+                if not $rootScope.config.writePermissionGranted
+                    alert 'Permission denied'
+                    $state.go 'home'
+                return
+        ]
+
         # Set up the states
         $stateProvider
         .state 'home',
@@ -46,6 +56,7 @@
             controller: 'ScanSingleObjectCtrl as scanSingleObject'
             params:
                 scanInputValue: ''
+            onEnter: permissionDeniedCheck

         .state  'listPersons',
             url: '/list/persons'
@@ -61,11 +72,13 @@
             url: '/import'
             templateUrl: 'static/templates/import.html'
             controller: 'ImportCtrl as import'
+            onEnter: permissionDeniedCheck

         .state  'database',
             url: '/database'
             templateUrl: 'static/templates/database.html'
             controller: 'DatabaseCtrl as database'
+            onEnter: permissionDeniedCheck

         return
 ]


Fix index offset being incorrect if element is coming from outside

https://github.com/flowapp/droppable.js/commit/63a481f2adf10051619538a098327a647c53c472

Fixed a problem with index being too large when `options.manual` was true in
sortable. However, it didn't take into account the possibility that the items
you were sorting were coming from an _outside_ source, so it could be
subtracting when it wasn't actually needed, making the index too _small_.

This checks each element being sorted and only subtracts from the index if the
element is contained in the original container to begin with.

--- src/sortable.coffee
+++ src/sortable.coffee
@@ -69,7 +69,8 @@
       # so placeholder will be off by elements.length when being dragged
       # "down" beneath the elements.
       if @options.manual && _index > data.originalIndex.start
-        _index -= $elements.length
+        for element in $elements when @el.contains(element)
+          _index -= 1

       # If were moving the elements "up", then the placeholder would be above where the
       # elements came from, so we'll need to -1 from the originalIndex indices.


Apply overflow only to body

Apply overflow only to body

--- src/creative.coffee
+++ src/creative.coffee
@@ -18,8 +18,8 @@
   _append_embedded: ->
     @loader = document.createElement("div")
     @loader.setAttribute("class", "infeedl--embedded--loader")
-    @overflow = Infeedl.$("html,body").css("overflow")
-    Infeedl.$("html,body").css(overflow: "hidden")
+    @overflow = Infeedl.$("body").css("overflow")
+    Infeedl.$("body").css(overflow: "hidden")
     Infeedl.$("body")[0].appendChild(@loader)

     @iframe = document.createElement("iframe")
@@ -53,7 +53,7 @@
   _remove_embedded: ->
     @iframe = null
     Infeedl.$(".infeedl--embedded").remove()
-    Infeedl.$("html,body").css(overflow: @overflow)
+    Infeedl.$("body").css(overflow: @overflow)
     # console?.log("[INFEEDL] Creative ##{@creative.id}: embedded removed")

   _interpolations: ->


Fix use of env in Linux

Fix use of env in Linux

Needs -S to split up shebang argument

--- src/svgtiler.coffee
+++ src/svgtiler.coffee
@@ -1,4 +1,4 @@
-`#!/usr/bin/env node --enable-source-maps
+`#!/usr/bin/env -S node --enable-source-maps
 (function() {
 `


Rollback 89e3f0e05edc8f99ead2cc2cc3f61df8ea71b961

--- src/tabelog.coffee
+++ src/tabelog.coffee
@@ -51,12 +51,12 @@
       restaurant = _.sample(restaurants, 1)[0]
       console.log restaurant
       if restaurant
+        msg.send restaurant.image
         messages = []
         messages.push restaurant.name
         if restaurant.stars? and restaurant.stars != '' and restaurant.score? and restaurant.score != ''
           messages.push restaurant.stars + ' ' + restaurant.score
         messages.push restaurant.link
-        messages.push restaurant.image
         message = messages.join("\n")
       msg.send message


Started work on filters

Started work on filters

--- src/template.coffee
+++ src/template.coffee
@@ -3,7 +3,8 @@
     DOM_REGEX                = /[^>]+>/
     BINDING_REGEX            = /\s(data\-[\w\d\-]+)/gim
     SUBSTITUTION_REGEX       = /#\{(.*?)\}/g
-    BINDINGS                 = []
+    BINDINGS                 = {}
+    FILTERS                  = {}
     INTERPOLATION_ATTRIBUTES = ['title', 'style', 'class', 'alt', 'id', 'href']

     class Template
@@ -83,6 +84,20 @@
             for {name, raw} in @vars
                 context.watch name, => @substitute context
             @substitute context
+
+    class Filter
+        # Apply transformation to variables coming from the context.
+        # Works very similar to bindings.
+        @bind: (name, fn)->
+            FILTERS[name] = fn
+
+        @get: (name)->
+            FILTERS[name]
+
+    Filter.bind 'urlize', (text)->
+        re = /(https*:\/\/[^\s]+)/g
+        text.replace(re, """$1""")
+

     class Binding
@@ -165,7 +180,13 @@
         vars = getVars str

         for {raw, name} in vars
+            [name, filters...] = name.split('|')
+
             value = context.get name
+
+            for filter in filters
+                value = Filter.get(filter) value
+
             if value?
                 str = str.replace raw, value
             else


Make transit route colors more opaque

Make transit route colors more opaque

--- src/transit.coffee
+++ src/transit.coffee
@@ -145,7 +145,7 @@
         for leg in legs
             points = (new L.LatLng(point[0], point[1]) for point in leg.legGeometry.points)
             color = google_colors[leg.routeType ? leg.mode]
-            style = {color: color, weight: 8, opacity: 0.2, clickable: false}
+            style = {color: color, weight: 8, opacity: 0.4, clickable: false}
             # For walking a dashed line is used
             if not leg.routeType?
                 style.weight = 10
@@ -156,7 +156,7 @@
             polyline = new L.Polyline points, style
             polyline.addTo route_layer # The route leg line is added to the routeLayer

-            style.opacity = 0.4
+            style.opacity = 0.8
             delete style.weight
             delete style.clickable
             if not leg.routeType?


Updated udefine.module.add to allow objects

--- src/udefine.coffee
+++ src/udefine.coffee
@@ -101,14 +101,18 @@
     globals: {}
     commonjs: {}

+    # TODO: Reflect if previously defined modules should be overwritten
     add: (name, value) ->
-      if value
-        if Array.isArray value
-          udefine.modules[v][name] = undefined for v in value
+      if typeof name is 'object'
+        @add key, val for key, val of name
+      else
+        if value
+          if Array.isArray value
+            udefine.modules[v][name] = undefined for v in value
+          else
+            udefine.modules.set name, value
         else
-          udefine.modules.set name, value
-      else
-        udefine.modules[platform][name] = undefined
+          udefine.modules[platform][name] = undefined
       @

     remove: (name) ->


Added injection API seperated from globals property

--- src/udefine.coffee
+++ src/udefine.coffee
@@ -30,7 +30,14 @@

         if Object.hasOwnProperty.call root.udefine.globals, name
           root.udefine.globals[name] = result
+
+        if Object.hasOwnProperty.call root.udefine.inject, name
+          do (injectName = name, origRoot = root) ->
+            {name, root} = root.udefine[injectName]
+            origRoot.udefine.inject(root, name)(result)
     result
+
+  root.udefine.inject = (obj, name) -> (res) -> obj[name] = res

   root.udefine.globals or= {}
   root.udefine.commonjs or= {}


Optional firing at a specific target

Optional firing at a specific target

--- src/weapons.coffee
+++ src/weapons.coffee
@@ -69,8 +69,8 @@

   # Fire at a random entity from all target groups
-  fire: ->
-    target = @randomTarget()
+  fire: (target=null) ->
+    target ?= @randomTarget()

     if @isActive() && target.isAlive
       x = Math.abs(@holder.midx() - target.midx())  # x-distance between enemy & target


* change to fat arrow context-specific methods

--- src/dendrite.coffee
+++ src/dendrite.coffee
@@ -66,7 +66,7 @@

   @return [Object] handler { topics: topics, callback: callback, watchdog: undefined, context: context } or throw exception on invalid arguments
   ###
-  subscribe: (topics, callback, context = {}) ->
+  subscribe: (topics, callback, context = {}) =>
     @subscribeGuarded topics, callback, undefined, context

   ###
@@ -106,7 +106,7 @@
   @see #subscribe
   @return [Object] handler { topics: topics, callback: callback, watchdog: watchdog, context: context } or throw exception on invalid arguments
   ###
-  subscribeGuarded: (topics, callback, watchdog, context = {}) ->
+  subscribeGuarded: (topics, callback, watchdog, context = {}) =>

     # Make sure that each argument is valid
     unless _.isString(topics) or _.isFunction(callback) or ( not watchdog? or _.isFunction watchdog )
@@ -161,7 +161,7 @@

   @return [Object]  *this* for chaining
   ###
-  unsubscribe: (topics, callback, context) ->
+  unsubscribe: (topics, callback, context) =>

     # If the handler was used we are need to parse args
     if topics.topics
@@ -217,7 +217,7 @@

   @return [Object] *this* for chaining
   ###
-  publish: (topics, data...) ->
+  publish: (topics, data...) =>
     @_publisher 'sync', topics, data
     this

@@ -225,7 +225,7 @@
   Alias for {#publish}
   @return [Object] *this* for chaining
   ###
-  publishSync: (topics, data...) ->
+  publishSync: (topics, data...) =>
     @_publisher 'sync', topics, data
     this

@@ -240,7 +240,7 @@
   See {#publish} for all info
   @return [Object] *this* for chaining
   ###
-  publishAsync: (topics, data...) ->
+  publishAsync: (topics, data...) =>
     @_publisher 'async', topics, data
     this

@@ -253,7 +253,7 @@
   See {#publish} for all info
   @return [Array] list of all listened topics
   ###
-  getListenedTopicsList: ->
+  getListenedTopicsList: =>
     topic for topic, listiners of @_subscriptions_ when listiners.length

@@ -266,14 +266,14 @@
   @private
   @return [Boolean] true if Dendrite is publishing, false is idle
   ###
-  _isPublishing: ->
+  _isPublishing: =>
     !!@_publishing_counter_

   ###
   Self-incapsulate @_publishing_counter_ properties to internal methods
   @private
   ###
-  _publishingInc: ->
+  _publishingInc: =>
     @_publishing_counter_ += 1
     null

@@ -281,7 +281,7 @@
   Self-incapsulate @_publishing_counter_ properties to internal methods
   @private
   ###
-  _publishingDec: ->
+  _publishingDec: =>
     unless @_isPublishing
       throw Error """
                     Error on decrement publishing counter
@@ -295,7 +295,7 @@
   @private
   @return [Integer] unique task number
   ###
-  _getNextTaskNumber: ->
+  _getNextTaskNumber: =>
     @_tasks_counter_ += 1

   ###
@@ -304,7 +304,7 @@
   @param level [String] verbose level name
   @return [Integer] verbose level
   ###
-  _parseVerboseLevel: (level) ->
+  _parseVerboseLevel: (level) =>
     # default level is ERROR
     unless level?
       return ERROR
@@ -326,7 +326,7 @@
   @param type [String] engine type name
   @return [Array<publish, unsubscribe>] engine or throw exception on invalid arguments
   ###
-  _publisherEngine: (type) ->
+  _publisherEngine: (type) =>
     # we are need to have reference to this object itself
     self = @

@@ -353,7 +353,7 @@
   @param topics [String] topic names
   @param data [Array] any kind of data(s)
   ###
-  _publisher: (type, topics, data) ->
+  _publisher: (type, topics, data) =>

     # if somthing go wrong
     unless _.isString(topics)
@@ -406,7 +406,7 @@
   Internal method for unsubscribe continue
   @private
   ###
-  _unsubscribeResume: ->
+  _unsubscribeResume: =>
     # its unimportant if unsubscribe queue is empty
     return unless @_unsubscribe_queue_.length

@@ -426,7 +426,7 @@
   Internal method for publish firing
   @private
   ###
-  _publishFiring: (topic, task, data) ->
+  _publishFiring: (topic, task, data) =>
     try
       task[0].apply task[1], [topic].concat data
     catch err