feat(widgets): makes widgets and instances collections private

--- app/assets/javascripts/awesome_ui/widgets.js.coffee
+++ app/assets/javascripts/awesome_ui/widgets.js.coffee
@@ -1,10 +1,18 @@
+
+
+#
+__widgets__ = {}
+
+# The `__instances__` object stores the returned instances of the various widgets,
+# stored by widget type and then mapped with their target DOM element as key.
+__instances__ = {}

 ## widgets

 # The `widgets` function is both the main module and the function
 # used to register the widgets to apply on a page.
 widgets = (name, selector, options={}, block) ->
-  unless widgets[name]?
+  unless __widgets__[name]?
     throw new Error "Unable to find widget '#{name}'"

   # The options specific to the widget registration and activation are
@@ -24,7 +32,7 @@

   # The widgets instances are stored in a Hash with the DOM element they
   # target as key. The instances hashes are stored per widget type.
-  instances = widgets.instances[name] ||= new widgets.Hash
+  instances = __instances__[name] ||= new widgets.Hash

   # This method execute a test condition for the given element. The condition
   # can be either a function or a value converted to boolean.
@@ -85,7 +93,7 @@
     Array::forEach.call elements, (element) ->
       return unless can_be_handled element

-      res = widgets[name] element, Object.create(options), elements
+      res = __widgets__[name] element, Object.create(options), elements
       element.className += " #{handled_class}"
       instances.set element, res
       block?.call element, element, res
@@ -104,10 +112,6 @@
       else
         document.addEventListener event, handler

-# The `instances` of the various widgets, stored by widget type and then
-# mapped with their target DOM element as key.
-widgets.instances = {}
-
 #### widgets.define

 # The `widgets.define` is used to create a new widget usable through the
@@ -121,7 +125,7 @@
 #
 # The `options` object will contains all the options passed to the `widgets`
 # method except the `on`, `if`, `unless` and `media` ones.
-widgets.define = (name, block) -> widgets[name] = block
+widgets.define = (name, block) -> __widgets__[name] = block

 #### widgets.release

@@ -130,18 +134,18 @@
 # It's the widget responsibility to clean up its dependencies during
 # the `dispose` call.
 widgets.release = (name) ->
-  widgets.instances[name].each (value) -> value?.dispose?()
+  __instances__[name].each (value) -> value?.dispose?()

 #### widgets.activate

 # Activates all the widgets instances of type `name`.
 widgets.activate = (name) ->
-  widgets.instances[name].each (value) -> value?.activate?()
+  __instances__[name].each (value) -> value?.activate?()

 #### widgets.deactivate

 # Deactivates all the widgets instances of type `name`.
 widgets.deactivate = (name) ->
-  widgets.instances[name].each (value) -> value?.deactivate?()
+  __instances__[name].each (value) -> value?.deactivate?()

 window.widgets = widgets


Add dashes to the matched characters

Add dashes to the matched characters

--- app/assets/javascripts/gemojifyjs/emojify.js.coffee
+++ app/assets/javascripts/gemojifyjs/emojify.js.coffee
@@ -1,6 +1,6 @@
 class Emojify
   constructor: ->
-    @normal_tags = /:\w+:/g
+    @normal_tags = /:[-\w]+:/g
     @smileys = [
             [/:-*\)/g, 'blush'],
             [/:-*o/gi, 'scream'],


Selector needn't be configurable

Selector needn't be configurable

--- app/assets/javascripts/local_time/controller.coffee
+++ app/assets/javascripts/local_time/controller.coffee
@@ -5,7 +5,6 @@
 {RelativeTime, strftime, t} = LocalTime

 class LocalTime.Controller
-  @selector: "time[data-local]:not([data-localized])"
   @interval: 60 * 1000

   constructor: ->
@@ -21,7 +20,7 @@
     @processElements()

   processElements: =>
-    elements = document.querySelectorAll(@constructor.selector)
+    elements = document.querySelectorAll("time[data-local]:not([data-localized])")
     @processElement(element) for element in elements
     elements.length


hopefully fix build

hopefully fix build

--- apps/favorites_follows/test/client/favorites.coffee
+++ apps/favorites_follows/test/client/favorites.coffee
@@ -40,14 +40,13 @@
             defaultArtworkCollection: -> return
         @view = new FavoritesView
           el: $ 'body'
-          collection: artworks
         done()

     afterEach ->
       Backbone.sync.restore()

     describe '#showEmptyHint', ->
-
+
       it 'shows hint for adding favorite artworks', ->
         @view.$el.html().should.include 'Add works to your favorites'


use SystemLanguages enum

use SystemLanguages enum

--- imports/api/messages/methods.coffee
+++ imports/api/messages/methods.coffee
@@ -1,4 +1,5 @@
 import SimpleSchema from 'simpl-schema'
+import SystemLanguages from '/imports/api/dropdowns/SystemLanguages.js';

 export Methods =

@@ -12,7 +13,7 @@
 				message: type: String
 				language:
 					type: String
-					allowedValues: ['de', 'en', 'fr', 'hu', 'it', 'pt', 'pl', 'ru']
+					allowedValues: SystemLanguages.allowedValues
 			.validator()
 		run: (args) -> if Meteor.isServer
 			newDoc =


Simplified unit test to clarify cleanup steps

--- test/credentials.spec.coffee
+++ test/credentials.spec.coffee
@@ -860,6 +860,6 @@
           expect(creds.getStorage('id')).to.equal('IDENTITY-ID2')
         setupCreds({LoginId: 'LOGINIDB'})
         expect(creds.getStorage('id')).not.to.equal('IDENTITY-ID2')
-        setupCreds({LoginId: 'LOGINIDA'})
+        creds.params.LoginId = 'LOGINIDA'
         creds.clearCachedId()


Update -> extend test for enum creation.

--- test/integration.spec.coffee
+++ test/integration.spec.coffee
@@ -277,9 +277,21 @@
         name: 'sample_enum_attribute'
         value: 'enum-new-key'

+      expectedNewEnumKeyAttr =
+        name: 'sample_enum_attribute'
+        value:
+          key: 'enum-new-key'
+          label: 'enum-new-key'
+
       newEnumKeyAttr2 =
         name: 'sample_enum_attribute'
         value: 'enum-3-new-key'
+
+      expectedNewEnumKeyAttr2 =
+        name: 'sample_enum_attribute'
+        value:
+          key: 'enum-3-new-key'
+          label: 'enum-3-new-key'

       sampleImport.products[0].masterVariant.attributes.push(existingEnumKeyAttr)
       sampleImport.products[0].masterVariant.attributes.push(newEnumKeyAttr)
@@ -287,15 +299,23 @@
       sampleImport.products[1].variants[0].attributes.push(existingEnumKeyAttr)
       sampleImport.products[1].variants[0].attributes.push(newEnumKeyAttr)

-      @import._processBatches(sampleImport.products)
-      .then =>
-        expect(@import._summary.created).toBe 2
-        done()
-      .catch done
-
-
-
-
-
-
-
+      predicate = 'masterVariant(sku="B3-717597")'
+
+      @import._processBatches(sampleImport.products)
+      .then =>
+        expect(@import._summary.created).toBe 2
+        @client.productProjections.where(predicate).staged(true).fetch()
+      .then (result) ->
+        filterPredicate1 = (element) -> _.isEqual(element,expectedNewEnumKeyAttr)
+        filterPredicate2 = (element) -> _.isEqual(element,expectedNewEnumKeyAttr2)
+        expect(_.find(result.body.results[0].masterVariant.attributes, filterPredicate1)).toBeDefined()
+        expect(_.find(result.body.results[0].masterVariant.attributes, filterPredicate2)).toBeDefined()
+        done()
+      .catch done
+
+
+
+
+
+
+


feat: atom ide

feat: atom ide

--- atom/.atom/config.cson
+++ atom/.atom/config.cson
@@ -1,8 +1,12 @@
 "*":
+  "atom-ide-ui":
+    "atom-ide-diagnostics-ui": {}
   core:
     autoHideMenuBar: true
     automaticallyUpdate: false
     disabledPackages: [
+      "platformio-ide"
+      "platformio-ide-debugger"
       "linter"
     ]
     ignoredNames: [
@@ -35,9 +39,13 @@
     pylsPlugins:
       pycodestyle:
         maxLineLength: 88
+      pydocstyle:
+        convention: "pep257"
+      pylint: {}
     python: "/usr/bin/python"
   "linter-ui-default":
     panelHeight: 238
+    showPanel: true
   minimap:
     plugins:
       "git-diff": true


use async instead of nested callbacks

use async instead of nested callbacks

--- src/run.coffee
+++ src/run.coffee
@@ -1,4 +1,5 @@
 net       = require("net")
+async     = require("async")
 settings  = require("./settings")
 send      = require("./send")
 listen    = require("./listen")
@@ -10,17 +11,26 @@
 tcp = net.connect options.port, options.host, () ->
   console.log "Connected to #{tcp.remoteAddress}:#{tcp.remotePort}" if options.verbose

-  # first send our files
-  send tcp, (err) ->
-    return console.error "#{err}" if err?
+  async.series [
+    (callback) -> send tcp, callback
+    (callback) -> tcp.write(".\n", callback)
+    (callback) -> listen tcp, callback

-    tcp.write(".\n")
+  ], (err, results) ->
+     return console.error "#{err}" if err?
+     console.log "Done" if options.verbose

-    # now listen for changes
-    listen tcp, (err) ->
-      return console.error "#{err}" if err?
+  # # first send our files
+  # send tcp, (err) ->
+  #   return console.error "#{err}" if err?

-      console.log "Done" if options.verbose
+  #   tcp.write(".\n")
+
+  #   # now listen for changes
+  #   listen tcp, (err) ->
+  #     return console.error "#{err}" if err?
+
+  #     console.log "Done" if options.verbose

 tcp.on "error", (err) ->
   console.error "#{err}"


Send message to window directly when passing BrowserWindow for ipc.send.

--- browser/api/lib/ipc.coffee
+++ browser/api/lib/ipc.coffee
@@ -1,5 +1,14 @@
 EventEmitter = require('events').EventEmitter
 send = process.atomBinding('ipc').send
+
+sendWrap = (channel, processId, routingId, args...) ->
+  BrowserWindow = require 'browser_window'
+  if processId?.constructor is BrowserWindow
+    window = processId
+    processId = window.getProcessId()
+    routingId = window.getRoutingId()
+
+  send channel, processId, routingId, args...

 class Ipc extends EventEmitter
   constructor: ->
@@ -12,6 +21,6 @@
     @sendChannel(processId, routingId, 'message', args...)

   sendChannel: (args...) ->
-    send('ATOM_INTERNAL_MESSAGE', args...)
+    sendWrap('ATOM_INTERNAL_MESSAGE', args...)

 module.exports = new Ipc


separates 'Add actor' from 'Add action' events

--- app/assets/javascripts/forms.coffee
+++ app/assets/javascripts/forms.coffee
@@ -15,9 +15,21 @@
     map = $($siblings[$siblings.length - 1]).find('.map-preview')[0]
     initPreviewMap($siblings[$siblings.length - 1])

-  $(document).on 'click', '.add_actors_fields, .add_actions_fields', (event) ->
+  $(document).on 'click', '.add_actors_fields', (event) ->
     regexp = new RegExp($(this).data('id'))
-    $('.add-relations').before($(this).data('fields').replace(regexp))
+    $('.add-relations-actors').before($(this).data('fields').replace(regexp))
+    event.preventDefault()
+    current_actor_action = $('.current-actor-wrapper .current-actor, .current-action-wrapper .current-action')
+    value = $('#actor_name, #act_name').val()
+    current_actor_action.text value
+    $('#actor_name, #act_name').on 'keyup', (e)->
+      current_actor_action.text e.currentTarget.value
+      return
+    showDatepicker()
+
+  $(document).on 'click', '.add_actions_fields', (event) ->
+    regexp = new RegExp($(this).data('id'))
+    $('.add-relations-actions').before($(this).data('fields').replace(regexp))
     event.preventDefault()
     current_actor_action = $('.current-actor-wrapper .current-actor, .current-action-wrapper .current-action')
     value = $('#actor_name, #act_name').val()


Allow Touch Events for Pan and Zoom

Allow Touch Events for Pan and Zoom

--- app/classifier/frame-annotator.cjsx
+++ app/classifier/frame-annotator.cjsx
@@ -79,6 +79,8 @@
       # Allow touch scrolling on subject for mobile and tablets
       unless taskDescription?.type is 'drawing' or taskDescription?.type is 'crop'
         svgStyle.pointerEvents = 'none'
+      if @props.panEnabled is true
+        svgStyle.pointerEvents = 'all'

     svgProps = {}


Fix an error in firefox when attached a file to a US, task or issue

--- app/coffee/services/resource.coffee
+++ app/coffee/services/resource.coffee
@@ -588,7 +588,6 @@
                 try
                     data = JSON.parse(evt.target.responseText)
                 catch
-                    # NOTE: HACK: In firefox evt.target.responseText is HTML instead json text Why? Why?
                     data = {}
                 defered.resolve(data)

@@ -606,11 +605,11 @@

         if progress?
             xhr.upload.addEventListener("progress", uploadProgress, false)
-
         xhr.addEventListener("load", uploadComplete, false)
         xhr.addEventListener("error", uploadFailed, false)
         xhr.open("POST", @gmUrls.api(apiUrlKey))
         xhr.setRequestHeader("Authorization", "Bearer #{@gmAuth.getToken()}")
+        xhr.setRequestHeader('Accept', 'application/json')
         xhr.send(formData)
         return defered.promise


Teamwork: Changed KD.utils.xssEncode to Encoder.XSSEncode.

--- client/CollaborativeWorkspace/panes/chatpane.coffee
+++ client/CollaborativeWorkspace/panes/chatpane.coffee
@@ -92,7 +92,7 @@
   appendToChatItem: (params) ->
     {details} = params
     @lastChatItem.messageList.addSubView new KDCustomHTMLView
-      partial  : KD.utils.xssEncode details.body
+      partial  : Encoder.XSSEncode details.body
       cssClass : details.cssClass

   updateDate: (timestamp) ->


activity: define `ActivityLikeSummaryView::updateActors` method

--- client/Social/Activity/views/likesummaryview.coffee
+++ client/Social/Activity/views/likesummaryview.coffee
@@ -32,6 +32,31 @@

         return KD.showError err  if err
         new ShowMoreDataModalView null, accounts
+
+
+  updateActors: ->
+
+    @fetchPreviewAccounts (err, accounts) =>
+
+      return KD.showError err  if err
+
+      for i in [0..accounts.length]
+        account = accounts[i]
+        continue  unless view = this["placeholder#{i}"]
+        view.destroySubViews()
+        view.addSubView new ProfileLinkView null, account
+        view = null
+
+      @setTemplate @pistachio()
+      @render()
+
+      {actorsCount} = @getData().interactions.like
+
+      @showMoreLink.updatePartial Math.max actorsCount - 3, 0
+
+      if accounts.length is 0
+      then @hide()
+      else @show()

   fetchPreviewAccounts: (callback) ->


Panel: Fixes for getting panes correctly.

--- client/app/CommonViews/workspace/panel/panel.coffee
+++ client/app/CommonViews/workspace/panel/panel.coffee
@@ -6,8 +6,9 @@

     super options, data

-    @headerButtons = {}
-    @panes         = []
+    @headerButtons  = {}
+    @panesContainer = []
+    @panes          = []

     @createHeader()
     @createHeaderButtons()  if options.buttons?.length
@@ -41,10 +42,10 @@
         title   : @getOptions().hint

   createLayout: ->
-    @container = new KDView
-      cssClass : "panel-container"
+    @container  = new KDView
+      cssClass  : "panel-container"

-    panesLength            = @getOptions().panes.length
+    panesLength = @getOptions().panes.length
     return  unless panesLength
     panelTypeByPaneLength  =
       "1"                  : "SingleLayout"
@@ -56,7 +57,7 @@

   createPanes: ->
     for paneOptions, index in @getOptions().panes
-      @createPane paneOptions, @getPaneByIndex index
+      @createPane paneOptions, @getPaneContainerByIndex index

   createPane: (paneOptions, targetContainer) ->
     paneTypesToPaneClass =
@@ -64,17 +65,20 @@
       "editor"           : EditorPane
       "video"            : VideoPane
       "preview"          : PreviewPane
-    PaneClass            = paneTypesToPaneClass[paneOptions.type]
+    paneType             = paneOptions.type
+    PaneClass            = paneTypesToPaneClass[paneType]
+    pane                 = new PaneClass paneOptions

-    targetContainer.addSubView new PaneClass paneOptions
+    targetContainer.addSubView pane
+    @panes.push pane

   # GETTERS #
-  getPaneByIndex: (index) ->
-    return @panes[index]
+  getPaneContainerByIndex: (index) ->
+    return  @panesContainer[index]

   # LAYOUT CREATOR HELPERS #
   createSplitView: (type, views) ->
-    return new KDSplitView {
+    return  new KDSplitView {
       resizable : yes
       sizes     : ["50%", "50%"]
       type
@@ -86,7 +90,7 @@
       cssClass : "panel-container"

     @container.addSubView view
-    @panes.push view
+    @panesContainer.push view

   createDoubleLayout: ->
     pane1     = new KDView
@@ -94,7 +98,7 @@
     splitView = @createSplitView "vertical", [pane1, pane2]

     @container.addSubView splitView
-    @panes.push pane1, pane2
+    @panesContainer.push pane1, pane2

   createTripleLayout: ->
     pane1           = new KDView
@@ -104,8 +108,7 @@
     baseSplit       = @createSplitView "vertical", [pane1, rightInnerSplit]

     @container.addSubView baseSplit
-
-    @panes.push pane1, pane2, pane3
+    @panesContainer.push pane1, pane2, pane3

   createQuadrupleLayout: ->
     pane1           = new KDView
@@ -117,8 +120,7 @@
     baseSplit         = @createSplitView "vertical", [leftInnerSplit, rightInnerSplit]

     @container.addSubView baseSplit
-
-    @panes.push pane1, pane2, pane3, pane4
+    @panesContainer.push pane1, pane2, pane3, pane4

   pistachio: ->
     """


Workspace: Code clean up. Removed commented codes.

--- client/app/CommonViews/workspace/panel/panel.coffee
+++ client/app/CommonViews/workspace/panel/panel.coffee
@@ -57,23 +57,14 @@
     else
       warn "no layout config or pane passed to create a panel"

-  # createPanes: ->
-  #   for paneOptions, index in @getOptions().panes
-  #     @createPane paneOptions, @getPaneContainerByIndex index
-
   createPane: (paneOptions) ->
     PaneClass            = @getPaneClass paneOptions.type
     paneOptions.delegate = @
     pane                 = new PaneClass paneOptions

-    # targetContainer.addSubView pane
     @panes.push pane
     @emit "NewPaneCreated", pane
     return  pane
-
-  # GETTERS #
-  # getPaneContainerByIndex: (index) ->
-  #   return  @panesContainer[index]

   getPaneClass: (paneType) ->
     paneTypesToPaneClass =
@@ -85,58 +76,6 @@
       "tabbedEditor"     : @TabbedEditorPaneClass

     return  paneTypesToPaneClass[paneType]
-
-  # createSplitView: (type, views) ->
-  #   splitView = new SplitViewWithOlderSiblings {
-  #     resizable : yes
-  #     sizes     : ["50%", "50%"]
-  #     type
-  #     views
-  #   }
-  #   splitView.on "ResizeDidStop", =>
-  #     for pane in @splitView.panelPanes
-  #       pane.getSubViews().first.emit "PaneResized"
-  #   return  splitView
-
-  # createSingleLayout: ->
-  #   view       = new KDView
-  #     cssClass : "panel-container"
-
-  #   @container.addSubView view
-  #   @panesContainer.push view
-
-  # createDoubleLayout: ->
-  #   pane1      = new KDView
-  #   pane2      = new KDView
-  #   @splitView = @createSplitView "vertical", [pane1, pane2]
-
-  #   @container.addSubView @splitView
-  #   @panesContainer.push pane1, pane2
-  #   @splitView.panelPanes = [pane1, pane2]
-
-  # createTripleLayout: ->
-  #   pane1           = new KDView
-  #   pane2           = new KDView
-  #   pane3           = new KDView
-  #   rightInnerSplit = @createSplitView "horizontal", [pane2, pane3]
-  #   @splitView      = @createSplitView "vertical", [pane1, rightInnerSplit]
-
-  #   @container.addSubView @splitView
-  #   @panesContainer.push pane1, pane2, pane3
-  #   @splitView.panelPanes = [pane1, pane2, pane3]
-
-  # createQuadrupleLayout: ->
-  #   pane1             = new KDView
-  #   pane2             = new KDView
-  #   pane3             = new KDView
-  #   pane4             = new KDView
-  #   leftInnerSplit    = @createSplitView "horizontal", [pane1, pane2]
-  #   rightInnerSplit   = @createSplitView "horizontal", [pane3, pane4]
-  #   @splitView        = @createSplitView "vertical",   [leftInnerSplit, rightInnerSplit]
-
-  #   @container.addSubView @splitView
-  #   @panesContainer.push pane1, pane2, pane3, pane4
-  #   @splitView.panelPanes = [pane1, pane2, pane3, pane4]

   showHintModal: ->
     options        = @getOptions()
@@ -154,7 +93,6 @@
   viewAppended: ->
     super
     @getDelegate().emit "NewPanelAdded", @
-    # @createPanes()

   pistachio: ->
     """


Use http instead https for vm domains.

Use http instead https for vm domains.

--- client/app/MainApp/filetree/itemviews/vmitem.coffee
+++ client/app/MainApp/filetree/itemviews/vmitem.coffee
@@ -23,7 +23,7 @@
       if not err and domains.length > 0
         @vmInfo.updatePartial """
           on
+          href="http://#{domains.first}" target="_blank">
           #{domains.first} VM
         """


fix tests

fix tests

--- test/01.coffee
+++ test/01.coffee
@@ -62,18 +62,20 @@
 		User.find {}, (err, results) ->
 			should(err).not.be.ok
 			results.should.be.instanceof(Array).and.have.lengthOf(2)
-			results = results.sort (a, b) -> a.num - b.num
-			results[0].name.should.equal "name2"
-			results[1].name.should.equal "name3"
+			results = results.map (r) -> r.name
+			results.should.containEql("name2")
+			results.should.containEql("name3")
+			results.should.not.containEql("name1")
 			done()

 	it "on find query with exec", (done) ->
 		User.find({}).exec (err, results) ->
 			should(err).not.be.ok
 			results.should.be.instanceof(Array).and.have.lengthOf(2)
-			results = results.sort (a, b) -> a.num - b.num
-			results[0].name.should.equal "name2"
-			results[1].name.should.equal "name3"
+			results = results.map (r) -> r.name
+			results.should.containEql("name2")
+			results.should.containEql("name3")
+			results.should.not.containEql("name1")
 			done()

 	it "on find query with append where", (done) ->
@@ -169,9 +171,10 @@
 			User.find().withoutpre (err, results) ->
 				should(err).not.be.ok
 				results.should.be.instanceof(Array).and.have.lengthOf(2)
-				results = results.sort (a, b) -> a.num - b.num
-				results[0].name.should.equal "name1"
-				results[1].name.should.equal "name3"
+				results = results.map (r) -> r.name
+				results.should.containEql("name1")
+				results.should.containEql("name3")
+				results.should.not.containEql("name2")
 				done()

 	it "on findOneAndRemove with exec", (done) ->
@@ -181,9 +184,10 @@
 			User.find().withoutpre (err, results) ->
 				should(err).not.be.ok
 				results.should.be.instanceof(Array).and.have.lengthOf(2)
-				results = results.sort (a, b) -> a.num - b.num
-				results[0].name.should.equal "name1"
-				results[1].name.should.equal "name3"
+				results = results.map (r) -> r.name
+				results.should.containEql("name1")
+				results.should.containEql("name3")
+				results.should.not.containEql("name2")
 				done()

 	it "on findOneAndUpdate", (done) ->


Fix horizontal scroll bar issue on tailer pane

--- client/ide/lib/workspace/panes/idetailerpane.coffee
+++ client/ide/lib/workspace/panes/idetailerpane.coffee
@@ -74,6 +74,8 @@
         path  : @file.getPath()
         watch : @bound 'handleFileUpdate'

+      ace.editor.renderer.setScrollMargin 0, 15, 0, 0
+
       @resize()

@@ -145,6 +147,7 @@
     line    = (content.split '\n').length

     @setCursor row: line, column: 0
+    @getAce().editor.scrollPageDown()

   resize: ->


+ unit testing added

+ unit testing added

--- test/property-manager.coffee
+++ test/property-manager.coffee
@@ -58,7 +58,8 @@

     describe '.contructor', ->
       it 'should create an object', ->
-        result = createObjectWith PM, makeArgs prop1: 121, prop2: 453, hidden:399, notExi:111
+        result = createObjectWith PM, makeArgs
+          prop1: 121, prop2: 453, hidden:399, notExi:111
         result.should.have.property 'hidden', 123
         result.should.have.property 'prop1', 121
         result.should.have.property 'prop2', 453
@@ -68,7 +69,8 @@
         result.should.have.property 'prop6', 'defaultValue'
         result.should.not.have.property 'notExi'
       it 'should create an object and assign options', ->
-        result = createObjectWith PM, makeArgs prop1: 121, prop2: 453, hidden:399, $prop5:111
+        result = createObjectWith PM, makeArgs
+          prop1: 121, prop2: 453, hidden:399, $prop5:111
         result.should.have.property '$prop5', 111
       it 'should create an object and not assign readonly', ->
         result = createObjectWith PM, makeArgs prop7: 121
@@ -84,7 +86,8 @@
                 value: defaultArr
             , true
             super
-        result = createObjectWith SPM2, makeArgs prop1: 121, prop2: 453, hidden:399, notExi:111
+        result = createObjectWith SPM2, makeArgs
+          prop1: 121, prop2: 453, hidden:399, notExi:111
         result.arr.should.not.be.equal defaultArr
       if defaultValueSupport
         it 'should create an object with an disable clone default array property', ->
@@ -99,7 +102,8 @@
                   clone:false
               , true
               super
-          result = createObjectWith SPM2, makeArgs prop1: 121, prop2: 453, hidden:399, notExi:111
+          result = createObjectWith SPM2, makeArgs
+            prop1: 121, prop2: 453, hidden:399, notExi:111
           result.arr.should.be.equal defaultArr
         it 'should create an object via meaningful name', ->
           class SPM
@@ -114,24 +118,31 @@

     describe '#toObject', ->
       it 'should convert to a plain object', ->
-        result = createObjectWith PM, makeArgs prop1: 121, prop2: 453, hidden:399, notExi:111, prop4:234, prop6:undefined
+        result = createObjectWith PM, makeArgs
+          prop1: 121, prop2: 453, hidden:399, notExi:111, prop4:234, prop6:undefined
         if not defaultValueSupport
-          result.toObject().should.be.deep.equal prop1: 121, prop2: 453, prop4: 234, prop7:719
+          result.toObject().should.be.deep.equal
+            prop1: 121, prop2: 453, prop4: 234, prop7:719
         else
           result.toObject().should.be.deep.equal prop1: 121, prop2: 453, prop4: 234
       it 'should convert to a plain object with options', ->
-        result = createObjectWith PM, makeArgs prop1: 121, prop2: 453, hidden:399, notExi:111, prop6:undefined
+        result = createObjectWith PM, makeArgs
+          prop1: 121, prop2: 453, hidden:399, notExi:111, prop6:undefined
         if not defaultValueSupport
-          result.toObject(prop1: 333, prop4:5).should.be.deep.equal prop1: 333, prop2: 453, prop4: 5, prop7:719
+          result.toObject(prop1: 333, prop4:5).should.be.deep.equal
+            prop1: 333, prop2: 453, prop4: 5, prop7:719
         else
-          result.toObject(prop1: 333, prop4:5).should.be.deep.equal prop1: 333, prop2: 453, prop4: 5
+          result.toObject(prop1: 333, prop4:5).should.be.deep.equal
+            prop1: 333, prop2: 453, prop4: 5
       if defaultValueSupport
         it 'should convert to a plain object with defaults', ->
-          result = createObjectWith PM, makeArgs prop1: 432, prop2: 453, hidden:399, notExi:111
+          result = createObjectWith PM, makeArgs
+            prop1: 432, prop2: 453, hidden:399, notExi:111
           result.toObject().should.be.deep.equal prop2: 453
         it 'should convert to a plain object with options and defaults', ->
           result = createObjectWith PM, makeArgs prop2: 453, hidden:399, notExi:111
-          result.toObject(prop3: 333, prop4:5).should.be.deep.equal prop3: 333, prop2: 453, prop4: 5
+          result.toObject(prop3: 333, prop4:5).should.be.deep.equal
+            prop3: 333, prop2: 453, prop4: 5
         it 'should convert to a plain object via meaningful name', ->
           class SPM
             inherits SPM, PM
@@ -146,7 +157,8 @@
           obj.should.be.deep.equal meaning: 121, prop1: 222
     describe '#toJSON', ->
       it 'should JSON.stringify()', ->
-        result = createObjectWith PM, makeArgs prop1: 121, prop2: 453, hidden:399, notExi:111, prop4: 1, prop6:undefined
+        result = createObjectWith PM, makeArgs
+          prop1: 121, prop2: 453, hidden:399, notExi:111, prop4: 1, prop6:undefined
         result = JSON.stringify(result)
         result = JSON.parse(result)
         if not defaultValueSupport
@@ -155,7 +167,8 @@
           result.should.be.deep.equal prop1: 121, prop2: 453, prop4: 1
       if defaultValueSupport
         it 'should JSON.stringify() with defaults', ->
-          result = createObjectWith PM, makeArgs prop1: 432, prop2: 453, hidden:399, notExi:111
+          result = createObjectWith PM, makeArgs
+            prop1: 432, prop2: 453, hidden:399, notExi:111
           result = JSON.stringify(result)
           result = JSON.parse(result)
           result.should.be.deep.equal prop2: 453
@@ -170,7 +183,8 @@
                   assigned: Properties.SMART_ASSIGN
                   assign: (value, dest, src, name)->extend {hi:'world'}, value
               , classAttrs
-          result = createObjectWith SPM, makeArgs prop1: 121, prop2: 453, hidden:399, notExi:111, assign1: sd:91
+          result = createObjectWith SPM, makeArgs
+            prop1: 121, prop2: 453, hidden:399, notExi:111, assign1: sd:91
           obj = {prop1:222}
           result.assignTo(obj)
           obj.should.be.deep.equal
@@ -186,7 +200,8 @@
                 'assign1':
                   assign: (value, dest, src, name)->extend {hi:'world'}, value
               , classAttrs
-          result = createObjectWith SPM, makeArgs prop1: 121, prop2: 453, hidden:399, notExi:111, assign1: sd:91
+          result = createObjectWith SPM, makeArgs
+            prop1: 121, prop2: 453, hidden:399, notExi:111, assign1: sd:91
           obj = {prop1:222}
           result.assignTo(obj)
           obj.should.be.deep.equal
@@ -194,29 +209,34 @@
             prop6: 'defaultValue'
             assign1: sd:91, hi: 'world'
       it 'should assign itself to another plain object', ->
-        result = createObjectWith PM, makeArgs prop1: 121, prop2: 453, hidden:399, notExi:111
+        result = createObjectWith PM, makeArgs
+          prop1: 121, prop2: 453, hidden:399, notExi:111
         obj = {prop1:222}
         result.assignTo(obj)
         obj.should.be.deep.equal
           prop1: 121, prop2: 453, prop3:undefined, prop4: null, $prop5: 'nonExport'
           prop6: 'defaultValue'
       it 'should assign itself to another plain object with exclude one', ->
-        result = createObjectWith PM, makeArgs prop1: 121, prop2: 453, hidden:399, notExi:111
+        result = createObjectWith PM, makeArgs
+          prop1: 121, prop2: 453, hidden:399, notExi:111
         obj = {prop1:222}
         result.assignTo(obj, 'prop2')
         obj.should.be.deep.equal
           prop1: 121, prop3:undefined, prop4: null, $prop5: 'nonExport'
           prop6: 'defaultValue'
       it 'should assign a plain object with exclude one', ->
-        result = createObjectWith PM, makeArgs prop1: 121, prop2: 453, hidden:399, notExi:111
+        result = createObjectWith PM, makeArgs
+          prop1: 121, prop2: 453, hidden:399, notExi:111
         obj = {prop1:222, prop2:91883}
         result.assign(obj, 'prop2')
         result.should.have.property 'prop1',222
         result.should.have.property 'prop2',453

       it 'should assign itself to another object', ->
-        result = createObjectWith PM, makeArgs prop1: 121, prop2: 453, hidden:399, notExi:111
-        obj = createObjectWith PM, makeArgs prop1: 1, prop2: 4, hidden:9, notExi:11, prop3: 11, prop4:11, $prop5: 'dd'
+        result = createObjectWith PM, makeArgs
+          prop1: 121, prop2: 453, hidden:399, notExi:111
+        obj = createObjectWith PM, makeArgs
+          prop1: 1, prop2: 4, hidden:9, notExi:11, prop3: 11, prop4:11, $prop5: 'dd'
         obj._assign = sinon.spy()
         result.assignTo(obj)
         obj.should.have.property 'hidden', 123
@@ -232,8 +252,10 @@

     describe '#isSame()', ->
       it 'should compare itself to another object', ->
-        result = createObjectWith PM, makeArgs prop1: 121, prop2: 453, hidden:399, notExi:111
-        obj = createObjectWith PM, makeArgs prop1: 1, prop2: 4, hidden:9, notExi:11, prop3: 11, prop4:11, $prop5: 'dd'
+        result = createObjectWith PM, makeArgs
+          prop1: 121, prop2: 453, hidden:399, notExi:111
+        obj = createObjectWith PM, makeArgs
+          prop1: 1, prop2: 4, hidden:9, notExi:11, prop3: 11, prop4:11, $prop5: 'dd'
         obj.isSame(result).should.be.false
         result.isSame(obj).should.be.false
         obj =
@@ -248,7 +270,8 @@

     describe '#mergeTo()', ->
       it 'should merge to itself to another object', ->
-        result = createObjectWith PM, makeArgs prop1: 121, prop2: 453, hidden:399, notExi:111
+        result = createObjectWith PM, makeArgs
+          prop1: 121, prop2: 453, hidden:399, notExi:111
         obj = {test: 123, prop4:4}
         result.mergeTo obj
         obj.should.be.deep.equal
@@ -260,7 +283,8 @@
           '$prop5': 'nonExport'
           prop6: 'defaultValue'
       it 'should merge to itself as a new plain object', ->
-        result = createObjectWith PM, makeArgs prop1: 121, prop2: 453, hidden:399, notExi:111
+        result = createObjectWith PM, makeArgs
+          prop1: 121, prop2: 453, hidden:399, notExi:111
         obj = result.mergeTo()
         obj.should.be.deep.equal
           prop1: 121
@@ -270,7 +294,8 @@
           '$prop5': 'nonExport'
           prop6: 'defaultValue'
       it 'should merge to itself to another object with exclude one property.', ->
-        result = createObjectWith PM, makeArgs prop1: 121, prop2: 453, hidden:399, notExi:111
+        result = createObjectWith PM, makeArgs
+          prop1: 121, prop2: 453, hidden:399, notExi:111
         obj = {test: 123, prop4:4}
         result.mergeTo obj, 'prop1'
         obj.should.be.deep.equal
@@ -282,7 +307,8 @@
           prop6: 'defaultValue'

       it 'should merge to itself to another object with exclude multi properties.', ->
-        result = createObjectWith PM, makeArgs prop1: 121, prop2: 453, hidden:399, notExi:111
+        result = createObjectWith PM, makeArgs
+          prop1: 121, prop2: 453, hidden:399, notExi:111
         obj = {test: 123, prop4:4}
         result.mergeTo obj, ['prop1', 'prop3']
         obj.should.be.deep.equal
@@ -294,13 +320,15 @@

       if defaultValueSupport
         it 'should merge to itself and skip default value', ->
-          result = createObjectWith PM, makeArgs prop1: 121, prop2: 453, hidden:399, notExi:111
+          result = createObjectWith PM, makeArgs
+            prop1: 121, prop2: 453, hidden:399, notExi:111
           obj = result.mergeTo(true)
           obj.should.be.deep.equal
             prop1: 121
             prop2: 453
         it 'should merge to an object and skip default value', ->
-          result = createObjectWith PM, makeArgs prop1: 121, prop2: 453, hidden:399, notExi:111
+          result = createObjectWith PM, makeArgs
+            prop1: 121, prop2: 453, hidden:399, notExi:111
           obj = test:123,prop4:4
           result.mergeTo(obj, true)
           obj.should.be.deep.equal
@@ -368,12 +396,15 @@

     describe '#exportTo()', ->
       it 'should exportTo a object and skip readonly property', ->
-        result = createObjectWith PM, makeArgs prop1: 121, prop2: 453, hidden:399, notExi:111, prop4:234, prop6:undefined
-        result.exportTo(null, null, null, true).should.be.deep.equal prop1: 121, prop2: 453, prop4: 234
-
-      if defaultValueSupport
-        it 'should exportTo a object and skip readonly property and not skip default value', ->
-          result = createObjectWith PM, makeArgs prop1: 121, prop2: 453, hidden:399, notExi:111, prop4:234, prop6:undefined
+        result = createObjectWith PM, makeArgs
+          prop1: 121, prop2: 453, hidden:399, notExi:111, prop4:234, prop6:undefined
+        result.exportTo(null, null, null, true).should.be.deep.equal
+          prop1: 121, prop2: 453, prop4: 234
+
+      if defaultValueSupport
+        it 'should exportTo a object and skip readonly and not skip default value', ->
+          result = createObjectWith PM, makeArgs
+            prop1: 121, prop2: 453, hidden:399, notExi:111, prop4:234, prop6:undefined
           result = result.exportTo(null, null, false, true)
           result.should.be.deep.equal
             prop1: 121
@@ -406,6 +437,22 @@
         ManagerClass::nonExported1stChar = '$'
     describe '#clone', ->
       it 'should clone object', ->
-        result = createObjectWith PM, makeArgs prop1: 121, prop2: 453, hidden:399, notExi:111, prop4:234, prop6:undefined
+        result = createObjectWith PM, makeArgs
+          prop1: 121, prop2: 453, hidden:399, notExi:111, prop4:234, prop6:undefined
         o = result.clone()
         o.isSame(result).should.be.true
+    describe '#assignPropertyTo', ->
+      if defaultValueSupport
+        it 'should assignPropertyTo', ->
+          class SPM
+            inherits SPM, PM
+            ManagerClass.defineProperties SPM,
+              extend
+                'propName':
+                  name: 'meaning'
+              , classAttrs
+          result = createObjectWith SPM, makeArgs meaning: 1221
+          result.should.have.property 'propName', 1221
+          obj = {}
+          result.assignPropertyTo(obj, result, 'meaning', 123, null,true)
+          obj.should.have.property 'propName', 123


Syntax converter will use single quotes for single-chars

--- src/syn.coffee
+++ src/syn.coffee
@@ -7,7 +7,10 @@
     r.unshift '('
     r.push ')'
   else if typeof input is 'string'
-    r.push '"' + input.replace(/\n/g, '\\n') + '"'
+    unless input.length == 1
+      r.push '"' + input.replace(/\n/g, '\\n') + '"'
+    else
+      r.push "'" + input.replace(/\n/g, '\\n') + "'"
   else if typeof input is 'function'
     r.push '(-> ...)'
   else if input instanceof Object


Fix texarea get value

Fix texarea get value

--- src/coffee/widget/helpers/rs-get-form-value.coffee
+++ src/coffee/widget/helpers/rs-get-form-value.coffee
@@ -10,9 +10,11 @@
         if (@$el.attr('type') == 'radio')
           return _getRadioButtonValue(@$el, @$parent)
         if (@$el.attr('type') == 'checkbox')
-          return @$el.is(':checked');
+          return @$el.is(':checked')
         return @$el.val()
       if (@$el.prop('tagName') == 'SELECT')
+        return @$el.val()
+      if (@$el.prop('tagName') == 'TEXTAREA')
         return @$el.val()

       return @$el.text()


searches what is put in the search box, output to console. however, exact word search only atm

--- bootstrap-magic.coffee
+++ bootstrap-magic.coffee
@@ -4,7 +4,6 @@
   for item in group.data
     flattenedMagic[item._id] = item
     flattenedMagicValues[item._id] = item.value
-

 ###
 # EXPORTS
@@ -85,6 +84,14 @@
   subCatId = BootstrapMagic.dictionary.currentSubCategory.get()
   return _.find bootstrap_magic_variables, (group) -> group._id is subCatId

+getSearched = ->
+  console.log "fm: ", flattenedMagic[item]
+  console.log "fmv: ", flattenedMagicValues
+
+  items = _.map flattenedMagic, mapVariableOverrides
+  searchFilter = _.filter items, (obj) => obj._id == searchTerms.get()
+  console.log "searched: ", searchFilter
+
 Template._bootstrap_magic.onCreated ->
   BootstrapMagic.start() if BootstrapMagic.start

@@ -108,7 +115,9 @@
   "searchInactive" : -> !searchTerms.get()

 Template._bootstrap_magic.events
-  'keyup .magic-search' : (e) -> searchTerms.set e.currentTarget.value
+  'keyup .magic-search' : (e) ->
+    searchTerms.set e.currentTarget.value
+    getSearched()

   'click .magic-filter-item' :(e) ->
     $filter = $(e.currentTarget)


Add operation class to mousedown selector

--- src/packages/command-panel/src/preview-list.coffee
+++ src/packages/command-panel/src/preview-list.coffee
@@ -17,7 +17,7 @@
     @on 'core:move-up', => @selectPreviousOperation(); false
     @on 'core:confirm', => @executeSelectedOperation()

-    @on 'mousedown', 'li', (e) =>
+    @on 'mousedown', 'li.operation', (e) =>
       @setSelectedOperationIndex(parseInt($(e.target).closest('li').data('index')))
       @executeSelectedOperation()


save to the correct page when Aloha change fires

--- src/scripts/helpers/backbone/views/editable.coffee
+++ src/scripts/helpers/backbone/views/editable.coffee
@@ -19,6 +19,7 @@
       @observers = {}

       @listenTo(@model, 'change:editable', @_toggleEditable)
+      @listenTo(@model, 'change:currentPage', @_makeUneditable)

     onAfterRender: () ->
       # Make editable after rendering if editable flag is already set
@@ -54,29 +55,43 @@
           else
             value = options.value

-          setChanged = (model, onEdit) =>
-            if /^currentPage\./.test(value)
-              model.set('currentPage.changed', true)
-              model.set('childChanged', true)

-              # Changing a module's title also change's a book's ToC
-              if /^currentPage.title$/.test(value)
-                model.set('changed', true)
-            else
-              model.set('changed', true)
+          # do not rely on `currentPage.` when setting the value because
+          # the currentPage may have changed in the meantime
+          if /^currentPage\./.test(value)
+            myModel = @model.asPage()
+            value = value.replace(/^currentPage\./, '')
+            isCurrentPage = true
+          else
+            myModel = @model
+            isCurrentPage = false

-            onEdit.apply(@) if typeof onEdit is 'function'
+          getValue = () ->
+            myModel.get(value)
+
+          setValue = (v) =>
+            return if myModel.get(value) is v
+
+            myModel.set(value, v)
+            myModel.set('changed', true)
+            @model.set('childChanged', true) if isCurrentPage
+
+            # Changing a module's title also change's a book's ToC
+            if isCurrentPage and value is 'title'
+              @model.set('changed', true)
+
+            options.onEdit.apply(@) if typeof options.onEdit is 'function'
+

           options.onBeforeEditable?($editable)

           switch options.type
             when 'textinput'
               $input = $('<input type="text" />')
-              $input.attr('placeholder', "Enter a #{value} here").val(@model.get(value))
+              $input.attr('placeholder', "Enter a #{value} here").val(getValue())
               $editable.html($input)
               $input.on 'change', () =>
-                @model.set(value, $input.val())
-                setChanged(@model, options.onEdit)
+                setValue($input.val())

             # Setup contenteditable
             when 'contenteditable'
@@ -87,8 +102,7 @@

                 @observers[selector] = new MutationObserver (mutations) =>
                   mutations.forEach (mutation) =>
-                    @model.set(value, $($editable.get(index)).html())
-                    setChanged(@model, options.onEdit)
+                    setValue($($editable.get(index)).html())

                 @observers[selector].observe($editable.get(index), options.config or observerConfig)

@@ -99,7 +113,7 @@
                 $editable.text('Starting up Aloha...')
                 # Wait for Aloha to start up
                 Aloha.ready () =>
-                  html = @model.get(value) or ''
+                  html = getValue() or ''
                   html += "<p> </p>" # Allow putting cursor after a Blockish. removed if empty.
                   $editable.html(html)
                   $editable.addClass('aloha-root-editable') # the semanticblockplugin needs this for some reason
@@ -113,8 +127,7 @@
                     # See aloha.coffee for where this is used
                     window.GLOBAL_UPLOADER_HACK = () =>
                       editableBody = alohaEditable.getContents()
-                      @model.set(value, editableBody)
-                      setChanged(@model, options.onEdit)
+                      setValue(editableBody)

                   # Update the model if an event for this editable was triggered
                   Aloha.bind 'aloha-smart-content-changed.updatemodel', (evt, d) =>
@@ -128,8 +141,7 @@
                       editableBody = alohaEditable.getContents()
                       editableBody = editableBody.trim() # Trim for idempotence
                       # Change the contents but do not update the Aloha editable area
-                      @model.set(value, editableBody)
-                      setChanged(@model, options.onEdit)
+                      setValue(editableBody)

             # Setup Select2
             when 'select2'
@@ -143,8 +155,7 @@

                 $editable.off 'change.editable'
                 $editable.on 'change.editable', (e) =>
-                  @model.set(value, $editable.select2('val'))
-                  setChanged(@model, options.onEdit)
+                  setValue($editable.select2('val'))

           options.onEditable?($editable)


much better string axis buffers

much better string axis buffers

--- src/viz/types/helpers/graph/includes/buffer.coffee
+++ src/viz/types/helpers/graph/includes/buffer.coffee
@@ -10,8 +10,10 @@
       domain = vars[axis].scale.viz.domain()

       if typeof domain[0] is "string"
-        domain.unshift "d3plus_buffer_first"
-        domain.push "d3plus_buffer_last"
+        i = domain.length
+        while i >= 0
+          domain.splice(i, 0, "d3plus_buffer_"+i)
+          i--
         range = vars[axis].scale.viz.range()
         range = buckets d3.extent(range), domain.length
         vars[axis].scale.viz.domain(domain).range(range)


GroupDashboard: Show content of the template, keep track of templates in settings

--- client/Dashboard/views/generalsettingsview.coffee
+++ client/Dashboard/views/generalsettingsview.coffee
@@ -52,6 +52,30 @@
       selectOptions           : [
         { title: "Loading stack templates...", disabled: yes }
       ]
+      nextElement             :
+        showTemplate          :
+          itemClass           : KDButtonView
+          title               : "Show Template"
+          cssClass            : "solid green mini hidden"
+          callback            : =>
+
+            { Stack } = @settingsForm.inputs
+            data = @_templates["_#{Stack.getValue()}"]
+            return new KDNotificationView title: "No data found!"  unless data
+
+            { title, description, rules, domains, machines, extras } = data
+            data = { title, description, rules, domains, machines, extras }
+
+            try
+              parsed = JSON.stringify data, null, 2
+            catch e
+              warn e; log data
+              return new KDNotificationView
+                title: "An error occured"
+
+            new KDModalView
+              content : "<pre>#{parsed}</pre>"
+

     formOptions.fields["Visibility settings"] =
       itemClass               : KDSelectBox
@@ -101,17 +125,34 @@
       Stack.removeSelectOptions()

       if err
+
         Stack.setSelectOptions "Failed to fetch templates": []
         warn err
+
+      else if templates.length is 0
+
+        Stack.setSelectOptions "No template available": []
+
       else
-        templates = ({title:t.title, value:t._id} for t in templates)
-        templates.push title: "Do not create anything.", value: "none"

-        Stack.setSelectOptions "Select stack template..." : templates
+        @_templates   = {}
+        selectOptions = []

-      if stackTemplates?.length > 0
-        Stack.setDefaultValue stackTemplates.first
-      else
-        Stack.setDefaultValue "none"
+        for t in templates
+          selectOptions.push { title:t.title, value:t._id }
+          @_templates["_#{t._id}"] = t
+
+        selectOptions.push title: "Do not create anything.", value: "none"
+
+        Stack.setSelectOptions "Select stack template..." : selectOptions
+
+        showButton = @settingsForm.inputs["Show Template"]
+        showButton.setCss margin: "7px"
+        showButton.show()
+
+        if stackTemplates?.length > 0
+          Stack.setDefaultValue stackTemplates.first
+        else
+          Stack.setDefaultValue "none"

   pistachio:-> "{{> @settingsForm}}"


Groups: Privacy setting is removed from general settings view

--- client/Dashboard/views/generalsettingsview.coffee
+++ client/Dashboard/views/generalsettingsview.coffee
@@ -63,16 +63,6 @@
           defaultValue      : Encoder.htmlDecode group.body ? ""
           placeholder       : 'Please enter a description here.'
           autogrow          : yes
-        "Privacy settings"  :
-          itemClass         : KDSelectBox
-          label             : "Privacy"
-          type              : "select"
-          name              : "privacy"
-          defaultValue      : group.privacy ? "public"
-          selectOptions     : [
-            { title : "Public",    value : "public" }
-            { title : "Private",   value : "private" }
-          ]
         "Visibility settings"  :
           itemClass         : KDSelectBox
           label             : "Visibility"


Cacheable returns a single instance of JStackTemplate

--- client/app/lib/providers/computecontroller.coffee
+++ client/app/lib/providers/computecontroller.coffee
@@ -970,9 +970,8 @@

     { baseStackId } = stack

-    remote.cacheable 'JStackTemplate', baseStackId, (err, templates) ->
+    remote.cacheable 'JStackTemplate', baseStackId, (err, template) ->
       return callback err  if err
-      [ template ] = templates
       return callback null, template or {}


Update comment: jsloader works at module-scope

--- common/lib/xmodule/xmodule/js/src/jsloader.coffee
+++ common/lib/xmodule/xmodule/js/src/jsloader.coffee
@@ -1,7 +1,8 @@
 class @JavascriptLoader
   ###
   Set of library functions that provide common interface for javascript loading
-  for all module types
+  for all module types. All functionality provided by JavascriptLoader should take
+  place at module scope, i.e. don't run jQuery over entire page
   ###
   @setCollapsibles: (el) =>
     ###


allow checkout when balance === total

allow checkout when balance === total

--- common/methods/cartMethods/balanceCheckout.coffee
+++ common/methods/cartMethods/balanceCheckout.coffee
@@ -22,7 +22,7 @@
         order.orderTotal += delivery.deliveryMethod.cost * delivery.deliveryDays.length;
         order.balanceAmount += delivery.deliveryMethod.cost * delivery.deliveryDays.length;

-      if Roles.userIsInRole(customerId, 'allowNegativeBalance') or customer.profile.balance > order.orderTotal
+      if Roles.userIsInRole(customerId, 'allowNegativeBalance') or customer.profile.balance >= order.orderTotal
         Meteor.users.update customerId,
           $inc: 'profile.balance': -order.orderTotal


Fix URL redirect when in sub-directory

Fix URL redirect when in sub-directory

--- source/assets/javascripts/application.coffee
+++ source/assets/javascripts/application.coffee
@@ -36,4 +36,4 @@

 jQuery ($) ->
   if window.location.hash is ''
-    window.location = '/#/'
+    window.location.href = "#{ window.location.pathname }#/"


removes comments showing how I tried using fixtures first

--- source/javascripts/app/models/show.js.coffee
+++ source/javascripts/app/models/show.js.coffee
@@ -9,19 +9,15 @@
          today = new Date
          shows = Em.A()
          data.forEach (date) ->
+            # I create objects based on episodes  array. I don't need date now.
             date.episodes.forEach (show) ->
                # We don't want aired shows
                unless new Date(show.episode.first_aired_iso) < today
                   shows.pushObject(App.Show.create(show))
          shows

-# App.Show = DS.Model.extend
-#   date    : DS.attr('date')
-#   episodes: DS.attr()
-
-# App.Show.FIXTURES = [
+# Sample of data coming from json call
 #    {
-#       "id" : "1",
 #       "date":"2013-11-09",
 #       "episodes":[
 #          {
@@ -147,7 +143,6 @@
 #       ]
 #    },
 #    {
-#       "id": '2',
 #       "date":"2013-11-10",
 #       "episodes":[
 #          {
@@ -268,839 +263,6 @@
 #                   "hated":0
 #                }
 #             }
-#          },
-#          {
-#             "show":{
-#                "title":"Once Upon A Time (2011)",
-#                "year":2011,
-#                "url":"http:\/\/trakt.tv\/show\/once-upon-a-time-2011",
-#                "first_aired":1319425200,
-#                "first_aired_iso":"2011-10-23T20:00:00-04:00",
-#                "first_aired_localized":1319425200,
-#                "first_aired_utc":1319414400,
-#                "country":"United States",
-#                "overview":"Emma Swan, a 28-year-old bail bonds collector, has always been a fiercely independent person since being abandoned as a baby. Her son Henry, who she gave up for adoption years ago, finds and tries to convince Emma that she is Snow White's missing daughter. Henry shows Emma that in the fairytale, Prince Charming and Snow White sent her away to protect her. Emma doesn't believe him and takes Henry back to Storybrooke...",
-#                "runtime":60,
-#                "network":"ABC",
-#                "air_day":"Sunday",
-#                "air_day_localized":"Sunday",
-#                "air_day_utc":"Sunday",
-#                "air_time":"8:00pm",
-#                "air_time_localized":"8:00pm",
-#                "air_time_utc":"5:00pm",
-#                "certification":"TV-PG",
-#                "imdb_id":"tt1843230",
-#                "tvdb_id":"248835",
-#                "tvrage_id":"28385",
-#                "images":{
-#                   "poster":"http:\/\/slurm.trakt.us\/images\/posters\/10646.15.jpg",
-#                   "fanart":"http:\/\/slurm.trakt.us\/images\/fanart\/10646.15.jpg",
-#                   "banner":"http:\/\/slurm.trakt.us\/images\/banners\/10646.15.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":81,
-#                   "votes":4421,
-#                   "loved":4027,
-#                   "hated":394
-#                },
-#                "genres":[
-#                   "Drama",
-#                   "Fantasy"
-#                ]
-#             },
-#             "episode":{
-#                "season":3,
-#                "number":7,
-#                "title":"Dark Hollow",
-#                "overview":"Mr. Gold and Regina send Ariel back to Storybrooke with an item that will allow Belle to locate a hidden artifact that could help take down Pan. But unbeknownst to them, two men have broken into the town with the intent to stop them \u2013 at all costs. Meanwhile, Emma, Neal and Hook attempt to find Dark Hollow, where Peter Pan\u2019s shadow dwells, in order to capture it, and Mary Margaret is upset with David for keeping his poisoning a secret from her. ",
-#                "url":"http:\/\/trakt.tv\/show\/once-upon-a-time-2011\/season\/3\/episode\/7",
-#                "first_aired":1384142400,
-#                "first_aired_iso":"2013-11-10T20:00:00-05:00",
-#                "first_aired_localized":1384142400,
-#                "first_aired_utc":1384131600,
-#                "images":{
-#                   "screen":"http:\/\/slurm.trakt.us\/images\/episodes\/10646-3-7.15.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":100,
-#                   "votes":4,
-#                   "loved":4,
-#                   "hated":0
-#                }
-#             }
-#          },
-#          {
-#             "show":{
-#                "title":"See Dad Run",
-#                "year":2012,
-#                "url":"http:\/\/trakt.tv\/show\/see-dad-run",
-#                "first_aired":1349578800,
-#                "first_aired_iso":"2012-10-06T20:00:00-04:00",
-#                "first_aired_localized":1349578800,
-#                "first_aired_utc":1349568000,
-#                "country":"United States",
-#                "overview":"\"See Dad Run\" tells the story of David Hobbs (Scott Baio), who has spent the last decade playing the perfect father on one of TV\u2019s biggest sitcoms. But when the series ends and his wife resumes her own television career, he finds himself cast in his most challenging role to date: handling the day-to-day needs of three kids who\u2019ve grown accustomed to not having him around. David soon learns that playing a dad on TV is child\u2019s play compared to the real thing.",
-#                "runtime":30,
-#                "network":"Nick at Nite",
-#                "air_day":"Saturday",
-#                "air_day_localized":"Saturday",
-#                "air_day_utc":"Saturday",
-#                "air_time":"8:00pm",
-#                "air_time_localized":"8:00pm",
-#                "air_time_utc":"5:00pm",
-#                "certification":"TV-PG",
-#                "imdb_id":"tt2382108",
-#                "tvdb_id":"262266",
-#                "tvrage_id":"32703",
-#                "images":{
-#                   "poster":"http:\/\/slurm.trakt.us\/images\/posters\/18869.jpg",
-#                   "fanart":"http:\/\/slurm.trakt.us\/images\/fanart\/18869.jpg",
-#                   "banner":"http:\/\/slurm.trakt.us\/images\/banners\/18869.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":62,
-#                   "votes":17,
-#                   "loved":14,
-#                   "hated":3
-#                },
-#                "genres":[
-#                   "Comedy"
-#                ]
-#             },
-#             "episode":{
-#                "season":2,
-#                "number":11,
-#                "title":"See Dad See Dad Run",
-#                "overview":"",
-#                "url":"http:\/\/trakt.tv\/show\/see-dad-run\/season\/2\/episode\/11",
-#                "first_aired":1384142400,
-#                "first_aired_iso":"2013-11-10T20:00:00-05:00",
-#                "first_aired_localized":1384142400,
-#                "first_aired_utc":1384131600,
-#                "images":{
-#                   "screen":"http:\/\/slurm.trakt.us\/images\/fanart\/18869-940.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":0,
-#                   "votes":0,
-#                   "loved":0,
-#                   "hated":0
-#                }
-#             }
-#          },
-#          {
-#             "show":{
-#                "title":"Austin & Ally",
-#                "year":2011,
-#                "url":"http:\/\/trakt.tv\/show\/austin-and-ally",
-#                "first_aired":1322886600,
-#                "first_aired_iso":"2011-12-02T20:30:00-05:00",
-#                "first_aired_localized":1322886600,
-#                "first_aired_utc":1322875800,
-#                "country":"United States",
-#                "overview":"A comedy about the unique relationship between a young songwriter, Ally Dawson, and Austin Moon, the overnight internet sensation who gains sudden notoriety after performing one of Ally's songs. Austin and Ally struggle with how to maintain and capitalize on Austin's newfound fame. Austin is more of a rebel type who doesn't follow the rules and is somewhat immature for his age, while Ally is conservative yet self-conscious.",
-#                "runtime":30,
-#                "network":"Disney Channel",
-#                "air_day":"Friday",
-#                "air_day_localized":"Friday",
-#                "air_day_utc":"Friday",
-#                "air_time":"8:30pm",
-#                "air_time_localized":"8:30pm",
-#                "air_time_utc":"5:30pm",
-#                "certification":"TV-G",
-#                "imdb_id":"tt1830491",
-#                "tvdb_id":"254245",
-#                "tvrage_id":"29965",
-#                "images":{
-#                   "poster":"http:\/\/slurm.trakt.us\/images\/posters\/13377.jpg",
-#                   "fanart":"http:\/\/slurm.trakt.us\/images\/fanart\/13377.jpg",
-#                   "banner":"http:\/\/slurm.trakt.us\/images\/banners\/13377.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":86,
-#                   "votes":19,
-#                   "loved":17,
-#                   "hated":2
-#                },
-#                "genres":[
-#                   "Comedy"
-#                ]
-#             },
-#             "episode":{
-#                "season":3,
-#                "number":3,
-#                "title":"Presidents & Problems",
-#                "overview":"Following the last show of Austin\u2019s tour, the gang does some sight-seeing at a Washington D.C. museum, where Austin accidentally gets stuck to a priceless object and must find a way to return it before performing for the President.",
-#                "url":"http:\/\/trakt.tv\/show\/austin-and-ally\/season\/3\/episode\/3",
-#                "first_aired":1384144200,
-#                "first_aired_iso":"2013-11-10T20:30:00-05:00",
-#                "first_aired_localized":1384144200,
-#                "first_aired_utc":1384133400,
-#                "images":{
-#                   "screen":"http:\/\/slurm.trakt.us\/images\/fanart\/13377-940.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":0,
-#                   "votes":0,
-#                   "loved":0,
-#                   "hated":0
-#                }
-#             }
-#          },
-#          {
-#             "show":{
-#                "title":"Instant Mom",
-#                "year":2013,
-#                "url":"http:\/\/trakt.tv\/show\/instant-mom",
-#                "first_aired":1380511800,
-#                "first_aired_iso":"2013-09-29T20:30:00-04:00",
-#                "first_aired_localized":1380511800,
-#                "first_aired_utc":1380501000,
-#                "country":"United States",
-#                "overview":"\"Instant Mom\" follows young party girl Stephanie who trades in cosmos for carpools when she marries an older man, Charlie, with three kids. Stephanie slowly grows into her role as a full-time stepmom while struggling to maintain some sense of her fun-loving, slightly irresponsible life.",
-#                "runtime":30,
-#                "network":"Nick at Nite",
-#                "air_day":"Sunday",
-#                "air_day_localized":"Sunday",
-#                "air_day_utc":"Sunday",
-#                "air_time":"8:30pm",
-#                "air_time_localized":"8:30pm",
-#                "air_time_utc":"5:30pm",
-#                "certification":"",
-#                "imdb_id":"tt2545498",
-#                "tvdb_id":"269935",
-#                "tvrage_id":"32519",
-#                "images":{
-#                   "poster":"http:\/\/slurm.trakt.us\/images\/poster-dark.2.jpg",
-#                   "fanart":"http:\/\/slurm.trakt.us\/images\/fanart\/28880.2.jpg",
-#                   "banner":"http:\/\/slurm.trakt.us\/images\/banners\/28880.2.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":90,
-#                   "votes":1,
-#                   "loved":1,
-#                   "hated":0
-#                },
-#                "genres":[
-#                   "Comedy"
-#                ]
-#             },
-#             "episode":{
-#                "season":1,
-#                "number":7,
-#                "title":"Dances with She-Wolves",
-#                "overview":"Stephanie attempts to get more involved by participating on the parents\u2019 dance committee at James\u2019 school only to find the other mothers mean and unwelcoming to the too pretty, too excited, binder-ready Stephanie.",
-#                "url":"http:\/\/trakt.tv\/show\/instant-mom\/season\/1\/episode\/7",
-#                "first_aired":1384144200,
-#                "first_aired_iso":"2013-11-10T20:30:00-05:00",
-#                "first_aired_localized":1384144200,
-#                "first_aired_utc":1384133400,
-#                "images":{
-#                   "screen":"http:\/\/slurm.trakt.us\/images\/fanart\/28880-940.2.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":0,
-#                   "votes":0,
-#                   "loved":0,
-#                   "hated":0
-#                }
-#             }
-#          },
-#          {
-#             "show":{
-#                "title":"Boardwalk Empire",
-#                "year":2010,
-#                "url":"http:\/\/trakt.tv\/show\/boardwalk-empire",
-#                "first_aired":1284955200,
-#                "first_aired_iso":"2010-09-19T21:00:00-04:00",
-#                "first_aired_localized":1284955200,
-#                "first_aired_utc":1284944400,
-#                "country":"United States",
-#                "overview":"Boardwalk Empire is a period drama focusing on Enoch \"Nucky\" Thompson (based on the historical Enoch L. Johnson), a political figure who rose to prominence and controlled Atlantic City, New Jersey, during the Prohibition period of the 1920s and 1930s. Nucky interacts with several historical figures in both his personal and political life, including mobsters, politicians, government agents, and the common folk who look up to him. The federal government also takes an interest in the bootlegging and other illegal activities in the area, sending agents to investigate possible mob connections but also looking at Nucky's lifestyle\u2014expensive and lavish for a county political figure.",
-#                "runtime":60,
-#                "network":"HBO",
-#                "air_day":"Sunday",
-#                "air_day_localized":"Sunday",
-#                "air_day_utc":"Sunday",
-#                "air_time":"9:00pm",
-#                "air_time_localized":"9:00pm",
-#                "air_time_utc":"6:00pm",
-#                "certification":"TV-MA",
-#                "imdb_id":"tt0979432",
-#                "tvdb_id":"84947",
-#                "tvrage_id":"23561",
-#                "images":{
-#                   "poster":"http:\/\/slurm.trakt.us\/images\/posters\/121.13.jpg",
-#                   "fanart":"http:\/\/slurm.trakt.us\/images\/fanart\/121.13.jpg",
-#                   "banner":"http:\/\/slurm.trakt.us\/images\/banners\/121.13.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":89,
-#                   "votes":3122,
-#                   "loved":3028,
-#                   "hated":94
-#                },
-#                "genres":[
-#                   "Drama",
-#                   "Crime"
-#                ]
-#             },
-#             "episode":{
-#                "season":4,
-#                "number":10,
-#                "title":"White Horse Pike",
-#                "overview":"Tipped off by Sally Wheet, Nucky enlists Eli and Agent Knox to check out the extra cargo in Florida shipments. Margaret ponders a deal with Rothstein to improve her family\u2019s living conditions. Capone grows suspicious of Torrio; Nucky faces a dilemma; Eli makes peace with Willie.",
-#                "url":"http:\/\/trakt.tv\/show\/boardwalk-empire\/season\/4\/episode\/10",
-#                "first_aired":1384146000,
-#                "first_aired_iso":"2013-11-10T21:00:00-05:00",
-#                "first_aired_localized":1384146000,
-#                "first_aired_utc":1384135200,
-#                "images":{
-#                   "screen":"http:\/\/slurm.trakt.us\/images\/episodes\/121-4-10.13.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":70,
-#                   "votes":1,
-#                   "loved":1,
-#                   "hated":0
-#                }
-#             }
-#          },
-#          {
-#             "show":{
-#                "title":"Homeland",
-#                "year":2011,
-#                "url":"http:\/\/trakt.tv\/show\/homeland",
-#                "first_aired":1317614400,
-#                "first_aired_iso":"2011-10-02T21:00:00-04:00",
-#                "first_aired_localized":1317614400,
-#                "first_aired_utc":1317603600,
-#                "country":"United States",
-#                "overview":"While in Iraq, Carrie Mathison, a Central Intelligence Agency operations officer, had been warned by an asset that an American prisoner of war had been turned by al-Qaeda.  After conducting an unauthorized operation in Iraq, Carrie is put on probation and reassigned to the CIA's Counter-terrorism Center in Langley, Virginia.",
-#                "runtime":60,
-#                "network":"Showtime",
-#                "air_day":"Sunday",
-#                "air_day_localized":"Sunday",
-#                "air_day_utc":"Sunday",
-#                "air_time":"9:00pm",
-#                "air_time_localized":"9:00pm",
-#                "air_time_utc":"6:00pm",
-#                "certification":"TV-MA",
-#                "imdb_id":"tt1796960",
-#                "tvdb_id":"247897",
-#                "tvrage_id":"27811",
-#                "images":{
-#                   "poster":"http:\/\/slurm.trakt.us\/images\/posters\/10369.16.jpg",
-#                   "fanart":"http:\/\/slurm.trakt.us\/images\/fanart\/10369.16.jpg",
-#                   "banner":"http:\/\/slurm.trakt.us\/images\/banners\/10369.16.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":89,
-#                   "votes":7010,
-#                   "loved":6818,
-#                   "hated":192
-#                },
-#                "genres":[
-#                   "Drama",
-#                   "Suspense",
-#                   "Thriller"
-#                ]
-#             },
-#             "episode":{
-#                "season":3,
-#                "number":7,
-#                "title":"Gerontion",
-#                "overview":"Saul makes the gamble of his career; Carrie and Quinn try to contain a local police investigation; Mira's marriage is at a crossroads.",
-#                "url":"http:\/\/trakt.tv\/show\/homeland\/season\/3\/episode\/7",
-#                "first_aired":1384146000,
-#                "first_aired_iso":"2013-11-10T21:00:00-05:00",
-#                "first_aired_localized":1384146000,
-#                "first_aired_utc":1384135200,
-#                "images":{
-#                   "screen":"http:\/\/slurm.trakt.us\/images\/episodes\/10369-3-7.16.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":57,
-#                   "votes":3,
-#                   "loved":2,
-#                   "hated":1
-#                }
-#             }
-#          },
-#          {
-#             "show":{
-#                "title":"Revenge",
-#                "year":2011,
-#                "url":"http:\/\/trakt.tv\/show\/revenge",
-#                "first_aired":1316577600,
-#                "first_aired_iso":"2011-09-20T21:00:00-04:00",
-#                "first_aired_localized":1316577600,
-#                "first_aired_utc":1316566800,
-#                "country":"United States",
-#                "overview":"Emily Thorne rents a house in the Hamptons for the summer, seemingly intent on nothing more than enjoying a break in the popular resort. But it soon becomes clear that there's more to her visit. Her real name is Amanda Clarke and her father was framed for a crime he didn't commit and sent to prison for life and she has come to the Hamptons to seek revenge against the people who betrayed him and saw him sent to jail.",
-#                "runtime":60,
-#                "network":"ABC",
-#                "air_day":"Tuesday",
-#                "air_day_localized":"Tuesday",
-#                "air_day_utc":"Tuesday",
-#                "air_time":"9:00pm",
-#                "air_time_localized":"9:00pm",
-#                "air_time_utc":"6:00pm",
-#                "certification":"TV-14",
-#                "imdb_id":"tt1837642",
-#                "tvdb_id":"248837",
-#                "tvrage_id":"28387",
-#                "images":{
-#                   "poster":"http:\/\/slurm.trakt.us\/images\/posters\/10257.39.jpg",
-#                   "fanart":"http:\/\/slurm.trakt.us\/images\/fanart\/10257.39.jpg",
-#                   "banner":"http:\/\/slurm.trakt.us\/images\/banners\/10257.39.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":83,
-#                   "votes":2702,
-#                   "loved":2487,
-#                   "hated":215
-#                },
-#                "genres":[
-#                   "Drama"
-#                ]
-#             },
-#             "episode":{
-#                "season":3,
-#                "number":7,
-#                "title":"Resurgence",
-#                "overview":"Conrad hires famed party-girl turned PR mastermind Bizzy Preston to restore the Grayson family name, while Emily sinks her teeth deeper into her plan and Nolan has a revenge-agenda of his own.",
-#                "url":"http:\/\/trakt.tv\/show\/revenge\/season\/3\/episode\/7",
-#                "first_aired":1384146000,
-#                "first_aired_iso":"2013-11-10T21:00:00-05:00",
-#                "first_aired_localized":1384146000,
-#                "first_aired_utc":1384135200,
-#                "images":{
-#                   "screen":"http:\/\/slurm.trakt.us\/images\/episodes\/10257-3-7.39.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":0,
-#                   "votes":0,
-#                   "loved":0,
-#                   "hated":0
-#                }
-#             }
-#          },
-#          {
-#             "show":{
-#                "title":"The Good Wife",
-#                "year":2009,
-#                "url":"http:\/\/trakt.tv\/show\/the-good-wife",
-#                "first_aired":1253678400,
-#                "first_aired_iso":"2009-09-22T21:00:00-04:00",
-#                "first_aired_localized":1253678400,
-#                "first_aired_utc":1253667600,
-#                "country":"United States",
-#                "overview":"The Good Wife is a drama starring Emmy Award winner Julianna Margulies as a wife and mother who must assume full responsibility for her family and re-enter the workforce after her husband's very public sex and political corruption scandal lands him in jail.",
-#                "runtime":60,
-#                "network":"CBS",
-#                "air_day":"Tuesday",
-#                "air_day_localized":"Tuesday",
-#                "air_day_utc":"Tuesday",
-#                "air_time":"9:00pm",
-#                "air_time_localized":"9:00pm",
-#                "air_time_utc":"6:00pm",
-#                "certification":"TV-14",
-#                "imdb_id":"tt1442462",
-#                "tvdb_id":"95451",
-#                "tvrage_id":"22755",
-#                "images":{
-#                   "poster":"http:\/\/slurm.trakt.us\/images\/posters\/338.5.jpg",
-#                   "fanart":"http:\/\/slurm.trakt.us\/images\/fanart\/338.5.jpg",
-#                   "banner":"http:\/\/slurm.trakt.us\/images\/banners\/338.5.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":87,
-#                   "votes":1328,
-#                   "loved":1252,
-#                   "hated":76
-#                },
-#                "genres":[
-#                   "Drama"
-#                ]
-#             },
-#             "episode":{
-#                "season":5,
-#                "number":7,
-#                "title":"The Next Week",
-#                "overview":"Zach makes a discovery that leads Alicia and Cary to believe that the Lockhart\/Gardner firm is spying on them; Will helps one of Alicia's former clients; Clarke Hayden (Nathan Lane) offers financial advice to Florrick\/Agos.",
-#                "url":"http:\/\/trakt.tv\/show\/the-good-wife\/season\/5\/episode\/7",
-#                "first_aired":1384146000,
-#                "first_aired_iso":"2013-11-10T21:00:00-05:00",
-#                "first_aired_localized":1384146000,
-#                "first_aired_utc":1384135200,
-#                "images":{
-#                   "screen":"http:\/\/slurm.trakt.us\/images\/fanart\/338-940.5.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":90,
-#                   "votes":2,
-#                   "loved":2,
-#                   "hated":0
-#                }
-#             }
-#          },
-#          {
-#             "show":{
-#                "title":"The Walking Dead",
-#                "year":2010,
-#                "url":"http:\/\/trakt.tv\/show\/the-walking-dead",
-#                "first_aired":1288584000,
-#                "first_aired_iso":"2010-10-31T21:00:00-04:00",
-#                "first_aired_localized":1288584000,
-#                "first_aired_utc":1288573200,
-#                "country":"United States",
-#                "overview":"Based on the comic book series of the same name, The Walking Dead tells the story of a small group of survivors living in the aftermath of a zombie apocalypse.",
-#                "runtime":60,
-#                "network":"AMC",
-#                "air_day":"Sunday",
-#                "air_day_localized":"Sunday",
-#                "air_day_utc":"Sunday",
-#                "air_time":"9:00pm",
-#                "air_time_localized":"9:00pm",
-#                "air_time_utc":"6:00pm",
-#                "certification":"TV-14",
-#                "imdb_id":"tt1520211",
-#                "tvdb_id":"153021",
-#                "tvrage_id":"25056",
-#                "images":{
-#                   "poster":"http:\/\/slurm.trakt.us\/images\/posters\/124.25.jpg",
-#                   "fanart":"http:\/\/slurm.trakt.us\/images\/fanart\/124.25.jpg",
-#                   "banner":"http:\/\/slurm.trakt.us\/images\/banners\/124.25.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":89,
-#                   "votes":13168,
-#                   "loved":12607,
-#                   "hated":561
-#                },
-#                "genres":[
-#                   "Drama",
-#                   "Horror",
-#                   "Suspense"
-#                ]
-#             },
-#             "episode":{
-#                "season":4,
-#                "number":5,
-#                "title":"Internment",
-#                "overview":"Assorted enemies pressure Rick and the group; the survivors and the prison may reach a breaking point.",
-#                "url":"http:\/\/trakt.tv\/show\/the-walking-dead\/season\/4\/episode\/5",
-#                "first_aired":1384146000,
-#                "first_aired_iso":"2013-11-10T21:00:00-05:00",
-#                "first_aired_localized":1384146000,
-#                "first_aired_utc":1384135200,
-#                "images":{
-#                   "screen":"http:\/\/slurm.trakt.us\/images\/episodes\/124-4-5.25.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":83,
-#                   "votes":11,
-#                   "loved":10,
-#                   "hated":1
-#                }
-#             }
-#          },
-#          {
-#             "show":{
-#                "title":"Betrayal",
-#                "year":2013,
-#                "url":"http:\/\/trakt.tv\/show\/betrayal",
-#                "first_aired":1380517200,
-#                "first_aired_iso":"2013-09-29T22:00:00-04:00",
-#                "first_aired_localized":1380517200,
-#                "first_aired_utc":1380506400,
-#                "country":"United States",
-#                "overview":"A chance meeting leads photographer Sara Hadley and Attorney Jack McAllister to an undeniable instant attraction.  Sara\u2019s husband Drew is a successful prosecutor with political aspirations.  Jack is married to Elaine the daughter of his boss Thacher Karsten.  When Karsten's brother-in-law Lou is murdered, all evidence points to Karsten\u2019s son T.J. Jack, the company\u2019s lead council, will have to defend him.  For Sara\u2019s prosecutor husband Drew, this is the kind of high-profile murder case that can secure his political future.  Just as Sara and Jack\u2019s affair is starting, the lovers will find themselves in an impossible situation\u2013on opposite sides of a murder investigation.",
-#                "runtime":60,
-#                "network":"ABC",
-#                "air_day":"Sunday",
-#                "air_day_localized":"Sunday",
-#                "air_day_utc":"Sunday",
-#                "air_time":"10:00pm",
-#                "air_time_localized":"10:00pm",
-#                "air_time_utc":"7:00pm",
-#                "certification":"",
-#                "imdb_id":"tt2751074",
-#                "tvdb_id":"269647",
-#                "tvrage_id":"34645",
-#                "images":{
-#                   "poster":"http:\/\/slurm.trakt.us\/images\/posters\/23283.5.jpg",
-#                   "fanart":"http:\/\/slurm.trakt.us\/images\/fanart\/23283.5.jpg",
-#                   "banner":"http:\/\/slurm.trakt.us\/images\/banners\/23283.5.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":59,
-#                   "votes":37,
-#                   "loved":23,
-#                   "hated":14
-#                },
-#                "genres":[
-#                   "Drama"
-#                ]
-#             },
-#             "episode":{
-#                "season":1,
-#                "number":7,
-#                "title":"We Are Not Going To Baileys Harbor",
-#                "overview":"Neither Sara nor Jack's families will ever be the same after Drew's discovery of the affair. As Sara and Jack attempt to navigate their newly fractured relationships with their spouses and children, Elaine seeks support from an unlikely source. Meanwhile, a despondent Drew discovers information that could reopen Lou Mrozek\u2018s murder investigation, and Zarek, anxious to please Karsten, resorts to drastic measures to deal with Brandy.",
-#                "url":"http:\/\/trakt.tv\/show\/betrayal\/season\/1\/episode\/7",
-#                "first_aired":1384149600,
-#                "first_aired_iso":"2013-11-10T22:00:00-05:00",
-#                "first_aired_localized":1384149600,
-#                "first_aired_utc":1384138800,
-#                "images":{
-#                   "screen":"http:\/\/slurm.trakt.us\/images\/fanart\/23283-940.5.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":0,
-#                   "votes":0,
-#                   "loved":0,
-#                   "hated":0
-#                }
-#             }
-#          },
-#          {
-#             "show":{
-#                "title":"Eastbound & Down",
-#                "year":2009,
-#                "url":"http:\/\/trakt.tv\/show\/eastbound-and-down",
-#                "first_aired":1234764000,
-#                "first_aired_iso":"2009-02-15T22:00:00-05:00",
-#                "first_aired_localized":1234764000,
-#                "first_aired_utc":1234753200,
-#                "country":"United States",
-#                "overview":"Relief Pitcher Kenny Powers was poised to rule the Big Leagues, but two things got in his way: his fading fastball and his insufferable personality.  After a spectacular career flame-out, Kenny came home to Shelby, NC and picked up a job as a substitute gym teacher (mostly so his brother Dustin would stop threatening to kick him out).  He's spent every moment since then cashing in the last of his dying fame while plotting his inevitable comeback...one beer at a time.",
-#                "runtime":30,
-#                "network":"HBO",
-#                "air_day":"Sunday",
-#                "air_day_localized":"Sunday",
-#                "air_day_utc":"Sunday",
-#                "air_time":"10:00pm",
-#                "air_time_localized":"10:00pm",
-#                "air_time_utc":"7:00pm",
-#                "certification":"TV-MA",
-#                "imdb_id":"tt0866442",
-#                "tvdb_id":"82467",
-#                "tvrage_id":"21051",
-#                "images":{
-#                   "poster":"http:\/\/slurm.trakt.us\/images\/posters\/110.jpg",
-#                   "fanart":"http:\/\/slurm.trakt.us\/images\/fanart\/110.jpg",
-#                   "banner":"http:\/\/slurm.trakt.us\/images\/banners\/110.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":84,
-#                   "votes":683,
-#                   "loved":628,
-#                   "hated":55
-#                },
-#                "genres":[
-#                   "Comedy"
-#                ]
-#             },
-#             "episode":{
-#                "season":4,
-#                "number":7,
-#                "title":"Chapter 28",
-#                "overview":"Kenny's personal life takes a toll on his work; Stevie keeps up appearances in the face of adversity; Kenny learns a valuable Christmas lesson. ",
-#                "url":"http:\/\/trakt.tv\/show\/eastbound-and-down\/season\/4\/episode\/7",
-#                "first_aired":1384149600,
-#                "first_aired_iso":"2013-11-10T22:00:00-05:00",
-#                "first_aired_localized":1384149600,
-#                "first_aired_utc":1384138800,
-#                "images":{
-#                   "screen":"http:\/\/slurm.trakt.us\/images\/fanart\/110-940.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":0,
-#                   "votes":0,
-#                   "loved":0,
-#                   "hated":0
-#                }
-#             }
-#          },
-#          {
-#             "show":{
-#                "title":"Masters of Sex",
-#                "year":2013,
-#                "url":"http:\/\/trakt.tv\/show\/masters-of-sex",
-#                "first_aired":1380517200,
-#                "first_aired_iso":"2013-09-29T22:00:00-04:00",
-#                "first_aired_localized":1380517200,
-#                "first_aired_utc":1380506400,
-#                "country":"United States",
-#                "overview":"MASTERS OF SEX stars Michael Sheen and Lizzy Caplan, who will portray the real-life pioneers of the science of human sexuality, William Masters and Virginia Johnson. The series chronicles the unusual lives, romance and pop culture trajectory of Masters and Johnson. Their research touched off the sexual revolution and took them from a mid-western teaching hospital in St. Louis to the cover of Time magazine.",
-#                "runtime":60,
-#                "network":"Showtime",
-#                "air_day":"Sunday",
-#                "air_day_localized":"Sunday",
-#                "air_day_utc":"Sunday",
-#                "air_time":"10:00pm",
-#                "air_time_localized":"10:00pm",
-#                "air_time_utc":"7:00pm",
-#                "certification":"TV-MA",
-#                "imdb_id":"tt2137109",
-#                "tvdb_id":"261557",
-#                "tvrage_id":"32002",
-#                "images":{
-#                   "poster":"http:\/\/slurm.trakt.us\/images\/posters\/19038.1.jpg",
-#                   "fanart":"http:\/\/slurm.trakt.us\/images\/fanart\/19038.1.jpg",
-#                   "banner":"http:\/\/slurm.trakt.us\/images\/banners\/19038.1.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":80,
-#                   "votes":154,
-#                   "loved":142,
-#                   "hated":12
-#                },
-#                "genres":[
-#                   "Drama"
-#                ]
-#             },
-#             "episode":{
-#                "season":1,
-#                "number":7,
-#                "title":"All Together Now",
-#                "overview":"Masters and Johnson continue their sexual response study \u2013 now as participants \u2013 but Johnson fears their work may be interfering with Masters\u2019 home life. Libby pressures Dr. Haas to resume her fertility treatments in secret. Meanwhile, Haas struggles to let go of feelings for Virginia as his relationship with Vivian deepens. And Margaret Scully, caught in her infidelity, confronts her husband on the mounting problems in their marriage.",
-#                "url":"http:\/\/trakt.tv\/show\/masters-of-sex\/season\/1\/episode\/7",
-#                "first_aired":1384149600,
-#                "first_aired_iso":"2013-11-10T22:00:00-05:00",
-#                "first_aired_localized":1384149600,
-#                "first_aired_utc":1384138800,
-#                "images":{
-#                   "screen":"http:\/\/slurm.trakt.us\/images\/episodes\/19038-1-7.1.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":70,
-#                   "votes":2,
-#                   "loved":2,
-#                   "hated":0
-#                }
-#             }
-#          },
-#          {
-#             "show":{
-#                "title":"Witches of East End",
-#                "year":2013,
-#                "url":"http:\/\/trakt.tv\/show\/witches-of-east-end",
-#                "first_aired":1381122000,
-#                "first_aired_iso":"2013-10-06T22:00:00-04:00",
-#                "first_aired_localized":1381122000,
-#                "first_aired_utc":1381111200,
-#                "country":"United States",
-#                "overview":"Based on Melissa de la Cruz's best-selling novel, \"Witches of East End\" centers on the adventures of Joanna Beauchamp and her two adult daughters Freya and Ingrid -- both of whom unknowingly are their family's next generation of witches -- who lead seemingly quiet, uneventful modern day lives in Long Island's secluded seaside town of East Haven. When Freya becomes engaged to a young, wealthy newcomer, a series of events forces Joanna to admit to her daughters they are, in fact, powerful and immortal witches.",
-#                "runtime":60,
-#                "network":"Lifetime",
-#                "air_day":"Sunday",
-#                "air_day_localized":"Sunday",
-#                "air_day_utc":"Sunday",
-#                "air_time":"10:00pm",
-#                "air_time_localized":"10:00pm",
-#                "air_time_utc":"7:00pm",
-#                "certification":"",
-#                "imdb_id":"tt2288064",
-#                "tvdb_id":"267259",
-#                "tvrage_id":"32887",
-#                "images":{
-#                   "poster":"http:\/\/slurm.trakt.us\/images\/posters\/23335.1.jpg",
-#                   "fanart":"http:\/\/slurm.trakt.us\/images\/fanart\/23335.1.jpg",
-#                   "banner":"http:\/\/slurm.trakt.us\/images\/banners\/23335.1.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":79,
-#                   "votes":94,
-#                   "loved":88,
-#                   "hated":6
-#                },
-#                "genres":[
-#                   "Drama"
-#                ]
-#             },
-#             "episode":{
-#                "season":1,
-#                "number":6,
-#                "title":"Potentia Noctis",
-#                "overview":"",
-#                "url":"http:\/\/trakt.tv\/show\/witches-of-east-end\/season\/1\/episode\/6",
-#                "first_aired":1384149600,
-#                "first_aired_iso":"2013-11-10T22:00:00-05:00",
-#                "first_aired_localized":1384149600,
-#                "first_aired_utc":1384138800,
-#                "images":{
-#                   "screen":"http:\/\/slurm.trakt.us\/images\/fanart\/23335-940.1.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":0,
-#                   "votes":0,
-#                   "loved":0,
-#                   "hated":0
-#                }
-#             }
-#          },
-#          {
-#             "show":{
-#                "title":"Hello Ladies",
-#                "year":2013,
-#                "url":"http:\/\/trakt.tv\/show\/hello-ladies",
-#                "first_aired":1380519000,
-#                "first_aired_iso":"2013-09-29T22:30:00-04:00",
-#                "first_aired_localized":1380519000,
-#                "first_aired_utc":1380508200,
-#                "country":"United States",
-#                "overview":"Hello Ladies is loosely based on a 2011 stand-up routine and follows Merchant as an awkward, overly confident Englishman trying to date in Los Angeles \u2013 where his attempts to infiltrate the world of beautiful people are not successful.",
-#                "runtime":30,
-#                "network":"HBO",
-#                "air_day":"Sunday",
-#                "air_day_localized":"Sunday",
-#                "air_day_utc":"Sunday",
-#                "air_time":"10:30pm",
-#                "air_time_localized":"10:30pm",
-#                "air_time_utc":"7:30pm",
-#                "certification":"TV-MA",
-#                "imdb_id":"tt2378794",
-#                "tvdb_id":"265609",
-#                "tvrage_id":"32368",
-#                "images":{
-#                   "poster":"http:\/\/slurm.trakt.us\/images\/posters\/21479.13.jpg",
-#                   "fanart":"http:\/\/slurm.trakt.us\/images\/fanart\/21479.13.jpg",
-#                   "banner":"http:\/\/slurm.trakt.us\/images\/banners\/21479.13.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":63,
-#                   "votes":80,
-#                   "loved":55,
-#                   "hated":25
-#                },
-#                "genres":[
-#                   "Comedy"
-#                ]
-#             },
-#             "episode":{
-#                "season":1,
-#                "number":7,
-#                "title":"The Wedding",
-#                "overview":" Stuart tries to change the seating plan at a wedding; Jessica waits to hear about her call-back audition for a network show.",
-#                "url":"http:\/\/trakt.tv\/show\/hello-ladies\/season\/1\/episode\/7",
-#                "first_aired":1384151400,
-#                "first_aired_iso":"2013-11-10T22:30:00-05:00",
-#                "first_aired_localized":1384151400,
-#                "first_aired_utc":1384140600,
-#                "images":{
-#                   "screen":"http:\/\/slurm.trakt.us\/images\/fanart\/21479-940.13.jpg"
-#                },
-#                "ratings":{
-#                   "percentage":80,
-#                   "votes":1,
-#                   "loved":1,
-#                   "hated":0
-#                }
-#             }
 #          }
 #       ]
 #     }
-#   ]


fix grunt task so that it doesn't trigger infinite file watch loop

--- testSpecApp/Gruntfile.coffee
+++ testSpecApp/Gruntfile.coffee
@@ -7,7 +7,7 @@
     copy:
       "steroids-dist":
         src: "../dist/steroids.js"
-        dest: "www/components/steroids-js/steroids.js"
+        dest: "dist/components/steroids-js/steroids.js"
     shell:
       "steroids-build":
         command: "grunt"
@@ -17,7 +17,7 @@

   grunt.registerTask "default", [
     "shell:steroids-build"
-    "copy:steroids-dist"
     "steroids-make"
     "steroids-compile-sass"
+    "copy:steroids-dist"
   ]


Removed commas, not needed. Missed them in the first pass.

--- apps/vilive_web/priv/app/app.coffee
+++ apps/vilive_web/priv/app/app.coffee
@@ -3,12 +3,12 @@
 Ember.ENV.LOG_MODULE_RESOLVER = true

 Builder = Ember.Application.extend
-  LOG_ACTIVE_GENERATION: true,
-  LOG_MODULE_RESOLVER: true,
-  LOG_TRANSITIONS: true,
-  LOG_TRANSITIONS_INTERNAL: true,
-  LOG_VIEW_LOOKUPS: true,
-  modulePrefix: 'app',
+  LOG_ACTIVE_GENERATION: true
+  LOG_MODULE_RESOLVER: true
+  LOG_TRANSITIONS: true
+  LOG_TRANSITIONS_INTERNAL: true
+  LOG_VIEW_LOOKUPS: true
+  modulePrefix: 'app'
   Resolver: Resolver['default']

 `export default Builder`


Added Panning with Keyboard

Added Panning with Keyboard

--- js/main.coffee
+++ js/main.coffee
@@ -12,8 +12,9 @@
 require ['jquery', 'underscore', 'particle', 'vector'], ($, _, Particle, Vector) ->
   MAX_UPDATE_RATE = 1
   PARTICLE_COUNT = 100
-  MIN_MASS = 10
-  MAX_MASS = 1
+  MIN_MASS = 1
+  MAX_MASS = 10
+  PAN_SPEED = 10

   width = window.innerWidth
   height = window.innerHeight
@@ -27,6 +28,17 @@
     offset = offset.add new Vector
       x: -e.originalEvent.deltaX
       y: -e.originalEvent.deltaY
+
+  $(window).keydown (e) ->
+    e.preventDefault()
+    if e.keyCode == 37 || e.keyCode == 65
+      offset = offset.add new Vector(PAN_SPEED, 0)
+    if e.keyCode == 38 || e.keyCode == 87
+      offset = offset.add new Vector(0, PAN_SPEED)
+    if e.keyCode == 39 || e.keyCode == 68
+      offset = offset.add new Vector(-PAN_SPEED, 0)
+    if e.keyCode == 40 || e.keyCode == 83
+      offset = offset.add new Vector(0, -PAN_SPEED)

   ctx = $('canvas')[0].getContext '2d'


Fix coffeelint complaint

Fix coffeelint complaint

--- src/code/views/node-value-inspector-view.coffee
+++ src/code/views/node-value-inspector-view.coffee
@@ -28,7 +28,7 @@
     @props.graphStore.changeNode(isAccumulator:value)

   updateDefiningType: ->
-    @props.graphStore.changeNode(valueDefinedSemiQuantitatively:!@props.node.valueDefinedSemiQuantitatively)
+    @props.graphStore.changeNode(valueDefinedSemiQuantitatively: not @props.node.valueDefinedSemiQuantitatively)

   selectText: (evt) ->
     evt.target.select()


patch bug in toggleAppsGroup

patch bug in toggleAppsGroup

--- app/assets/javascripts/apps.js.coffee
+++ app/assets/javascripts/apps.js.coffee
@@ -25,7 +25,7 @@
       $('html, body').animate { scrollTop: activeTitle.offset().top }, 400

   toggleAppsGroups: ->
-    $(".app-title").on 'click', ->
+    $(".app-title").on 'click', =>
       if $(this).hasClass('show')
         @hideAppTitle($(this))
       else


minor change

minor change

--- app/assets/javascripts/lessons.coffee
+++ app/assets/javascripts/lessons.coffee
@@ -86,6 +86,7 @@
     bText = bText.substring(bText.indexOf(',') + 1, bText.length)
     bLink = '#' + bText.slice(1,bText.length).toLowerCase()
     bLink = bLink.replace('/', '-')
+    bLink = bLink.replace(' ', '-')
     $('.lessons-toc').append (b+1) + ' ' + toTitleCase(bText) + '  > '
     b++
   $('div.lessons-toc span:last-child').remove()


Bugfix: more date-related display bugs.

Bugfix: more date-related display bugs.

--- app/assets/javascripts/main.js.coffee
+++ app/assets/javascripts/main.js.coffee
@@ -9,11 +9,13 @@
     offset = date_offset.getTimezoneOffset()/-60
     $(".utc-time").each((index, element)->
       date = $(element).html()
-      localDatetime = Application.timestampToDateObject(date)
-      hours = localDatetime.getHours()
-      mins = localDatetime.getMinutes()
+      localDate = Application.timestampToDateObject(date)
+      hours = localDate.getHours()
+      mins = localDate.getMinutes()
       mins = "0#{mins}" if mins.toString().length == 1
-      if localDatetime.getDate() == today.getDate()
+      localDay = new Date(localDate.getFullYear(), localDate.getMonth(), localDate.getDate())
+      todayDay = new Date(today.getFullYear(), today.getMonth(), today.getDate())
+      if localDay.getTime() == todayDay.getTime()
         if hours < 12
           hours = 12 if hours == 0
           date_string = "#{hours}:#{mins} AM"
@@ -21,7 +23,7 @@
           hours = 24 if hours == 12
           date_string = "#{hours-12}:#{mins} PM"
       else
-        date_string = "#{localDatetime.getDate()} #{month[localDatetime.getMonth()]}"
+        date_string = "#{localDate.getDate()} #{month[localDate.getMonth()]}"
       $(element).html(String(date_string))
       $(element).removeClass('utc-time')
       $(element).addClass('relative-time')


pass() runs in the context of the action object.

--- lib/action.coffee
+++ lib/action.coffee
@@ -3,13 +3,12 @@

 exports = module.exports = action= (actions)->
   i= -1
-  actionobj= this
-  pass= ()->
+  pass= ()=>
     i+= 1
     if (actions.length > i)
-      actions[i].call(actionobj,pass)
+      actions[i].call(this,pass)
     else
-      actionobj.next()
+      @next()
   pass()

 exports.defaultActions= [