class ViewerAppController extends KDViewController

  KD.registerAppClass this,
    name         : "Viewer"
    route        : "/Develop"
    multiple     : yes
    openWith     : "forceNew"
    behavior     : "application"
    preCondition :

      condition  : (options, cb)->
        {path, vmName} = options
        return cb true  unless path
        path = FSHelper.plainPath path
        publicPath = path.replace \
          ///.*\/(.*\.#{KD.config.userSitesDomain})\/(.*)///, 'http://$1/$2'

        cb publicPath isnt path, {path: publicPath}

      failure    : (options, cb)->
        correctPath = \
          "/home/#{KD.nick()}/Sites/#{KD.nick()}.#{KD.config.userSitesDomain}/"
        KD.getSingleton("appManager").notify "File must be under: #{correctPath}"

  constructor:(options = {}, data)->

    options.view = new PreviewerView
      params     : options.params

    options.appInfo =
      title         : "Preview"
      cssClass      : "ace"

    super options, data

  open:(path)->
    @getView().openPath path

class ViewerAppController extends KDViewController

  KD.registerAppClass this,
    name         : "Viewer"
    route        : "/Develop"
    multiple     : yes
    openWith     : "forceNew"
    behavior     : "application"
    preCondition :

      condition  : (options, cb)->
        {path, vmName} = options
        return cb true  unless path
        path = FSHelper.plainPath path
        publicPath = path.replace \
          ///.*\/(.*\.#{KD.config.userSitesDomain})\/(.*)///, 'http://$1/$2'

        cb publicPath isnt path, {path: publicPath}

      failure    : (options, cb)->
        correctPath = \
          "/home/#{KD.nick()}/Web/"
        KD.getSingleton("appManager").notify "File must be under: #{correctPath}"

  constructor:(options = {}, data)->

    options.view = new PreviewerView
      params     : options.params

    options.appInfo =
      title         : "Preview"
      cssClass      : "ace"

    super options, data

  open:(path)->
    @getView().openPath path

Change folder to match new osKite default


goog.provide 'app.react.pages.NotFound'

class app.react.pages.NotFound

  ###*
    @constructor
  ###
  constructor: ->
    {div,h1,p} = React.DOM

    @create = React.createClass

      render: ->
        div className: 'notfound',
          h1 null, "This page isn't available"
          p null, "The link may be broken, or the page may have been removed."

goog.provide 'app.react.pages.NotFound'

class app.react.pages.NotFound

  ###*
    @param {app.Routes} routes
    @param {app.react.Touch} touch
    @constructor
  ###
  constructor: (routes, touch) ->
    {div,h1,p} = React.DOM
    {a} = touch.none 'a'

    @create = React.createClass

      render: ->
        div className: 'notfound',
          h1 null, "This page isn't available"
          p null, 'The link may be broken, or the page may have been removed.'
          a href: routes.home.createUrl(), 'Continue here please.'

Add link to home for 404 page.

Add link to home for 404 page.


openMultiPageModal = require '../../../components/multi_page_modal/index.coffee'
SpecialistView = require '../../../components/contact/general_specialist.coffee'

module.exports.init = ->
  $('.js-contact-specialist').click (e) ->
    e.preventDefault()
    new SpecialistView

  $('.js-multi-page-modal').click (e) ->
    e.preventDefault()
    openMultiPageModal $(this).data('id')

openMultiPageModal = require '../../../components/multi_page_modal/index.coffee'
SpecialistView = require '../../../components/contact/general_specialist.coffee'
FeebackView = require '../../../components/contact/feedback.coffee'

module.exports.init = ->
  $('.js-contact-specialist').click (e) ->
    e.preventDefault()
    new SpecialistView

  $('.js-contact-feedback').click (e) ->
    e.preventDefault()
    new FeebackView

  $('.js-multi-page-modal').click (e) ->
    e.preventDefault()
    openMultiPageModal $(this).data('id')

Add handler to invoke feedback modal

Add handler to invoke feedback modal


# Copyright 2012 The Apache Software Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http:#www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# ##core/zone
#
# Provides a default handler for the `events.zone.update` event, attached to the
# document body.
define ["core/spi", "core/events"],
  (spi, events) ->
    spi.domReady ->
      spi.body().on events.zone.update, (event) ->
        zone = spi.wrap this

        zone.trigger events.zone.willUpdate

        # TODO: purge existing children?

        zone.update event.memo

        zone.show() unless zone.visible()

        zone.trigger events.zone.didUpdate

    # No meaningful value is returned.
    true

# Copyright 2012 The Apache Software Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http:#www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# ##core/zone
#
# Provides a default handler for the `events.zone.update` event, attached to the
# document body.
define ["core/spi", "core/events"],
  (spi, events) ->
    spi.domReady ->
      spi.body().on events.zone.update, (event) ->

        this.trigger events.zone.willUpdate

        # TODO: purge existing children?

        this.update event.memo

        this.show() unless this.visible()

        this.trigger events.zone.didUpdate

    # No meaningful value is returned.
    return

Adjust initialization for this being the matched element's ElementWrapper


$ ->
  $('#currency').change ->
    $.ajax(
      type: 'POST'
      url: $(this).data('href')
      data:
        currency: $(this).val()
    ).done ->
      window.location.reload()

$ ->
  $('#currency').on 'change', ->
    $.ajax(
      type: 'POST'
      url: $(this).data('href')
      data:
        currency: $(this).val()
    ).done ->
      window.location.reload()

Use jQuery "on" for event hook.

Use jQuery "on" for event hook.


ValidationMixin =
  getInitialState: ->
    validationErrors: []
    hasErrors: false

  componentDidMount: ->
    if @props.validators
      @loadValidators()

  loadValidators: ->
    @validators = _.map @props.validators, (options, name) =>
      new window.validators[name].constructor(options)

  validate: (value, callback) ->
    if @props.validators
      newErrors = _.map @validators, (validator) =>
        validator.validate value, @props.displayName

      # There is probably a better way to do this
      newErrors = _.flatten newErrors
      newErrors = _.without newErrors, null, undefined

      @setState
        validationErrors: newErrors
        hasErrors: (newErrors.length != 0)
        , callback()
    else
      callback() if callback

module.exports = ValidationMixin

ValidationMixin =
  getInitialState: ->
    validationErrors: []
    hasErrors: false

  validate: (value, callback) ->
    if @props.validators
      newErrors = _.map @props.validators, (validator) =>
        validator.validate value, @props.displayName

      # There is probably a better way to do this
      newErrors = _.flatten newErrors
      newErrors = _.without newErrors, null, undefined

      @setState
        validationErrors: newErrors
        hasErrors: (newErrors.length != 0)
        , callback()
    else
      callback() if callback

module.exports = ValidationMixin

Update Validators to pass Instances instead of references


#= require ./abstract_binding

class Batman.DOM.ViewBinding extends Batman.DOM.AbstractBinding
  skipChildren: true
  onlyObserve: Batman.BindingDefinitionOnlyObserve.Data

  constructor: (definition) ->
    @superview = definition.view
    super

  dataChange: (viewClassOrInstance) ->
    return unless viewClassOrInstance?
    if viewClassOrInstance.isView
      @view = viewClassOrInstance
    else
      @view = new viewClassOrInstance

    @yieldName = "<#{@view.constructor.name}-#{@view._batmanID()}>"
    @superview.declareYieldNode(@yieldName, @node)
    @superview.subviews.set(@yieldName, @view)

  die: ->
    @superview.unset(@yieldName)
    @superview = null
    @view = null
    super

#= require ./abstract_binding

class Batman.DOM.ViewBinding extends Batman.DOM.AbstractBinding
  skipChildren: true
  onlyObserve: Batman.BindingDefinitionOnlyObserve.Data

  constructor: (definition) ->
    @superview = definition.view
    super

  dataChange: (viewClassOrInstance) ->
    return unless viewClassOrInstance?
    if viewClassOrInstance.isView
      @view = viewClassOrInstance
    else
      @view = new viewClassOrInstance

    @yieldName = "<#{@view.constructor.name || 'UnknownView'}-#{@view._batmanID()}>"
    @superview.declareYieldNode(@yieldName, @node)
    @superview.subviews.set(@yieldName, @view)

  die: ->
    @superview.unset(@yieldName)
    @superview = null
    @view = null
    super

Handle constructor.name being undefined in ViewBinding.


module.exports  =
  current: 'ami-bf235ad5'

  # Ordered by creation date
  list: [
    'ami-5dd50436'
    'ami-bf235ad5'
  ]

module.exports  =
  current: 'ami-4d552d27'

  # Ordered by creation date
  list: [
    'ami-5dd50436'
    'ami-bf235ad5'
    'ami-4d552d27'
  ]

Update test instance AMI identifier

Update test instance AMI identifier


microflo = (target) ->
    build = [
        "make -f ./node_modules/microflo-emscripten/Makefile"
        target
        "BUILD_DIR=build"
        "MICROFLO=./node_modules/.bin/microflo"
        "GRAPH=graph.fbp"
        "MICROFLO_SOURCE_DIR=`pwd`/node_modules/microflo/microflo"
        "LIBRARY=`pwd`/components/arduino-standard.json"
    ]
    return build.join ' '

module.exports = ->
  # Project configuration
  @initConfig

    # lint
    coffeelint:
      code:
        files:
          src: ['lib/*.coffee', 'spec/*.coffee']
        options:
          max_line_length:
            value: 100
            level: 'warn'
          no_trailing_semicolons:
            level: 'warn'

    # TODO: Browser build

    exec:
        microflo_emscripten: microflo "build-emscripten"

    mochaTest:
      nodejs:
        src: ['spec/*.coffee']
        options:
          reporter: 'spec'
          require: 'coffee-script/register'
          grep: process.env.TESTS

  # Grunt plugins used for building
  @loadNpmTasks 'grunt-exec'

  # Grunt plugins used for testing
  @loadNpmTasks 'grunt-mocha-test'

  # Our local tasks
  @registerTask 'build', [
    'exec:microflo_emscripten'
  ]

  @registerTask 'test', [
    'build'
    'mochaTest'
  ]

  @registerTask 'default', ['test']

microflo = (target) ->
    build = [
        "make -f ./node_modules/microflo-emscripten/Makefile"
        target
        "BUILD_DIR=build"
        "MICROFLO=./node_modules/.bin/microflo"
        "GRAPH=graph.fbp"
        "MICROFLO_SOURCE_DIR=`pwd`/node_modules/microflo/microflo"
        "PROJECT_DIR=`pwd`/node_modules/microflo-emscripten"
        "LIBRARYOPTION='--library `pwd`/components/arduino-standard.json'"
    ]
    return build.join ' '

module.exports = ->
  # Project configuration
  @initConfig

    # lint
    coffeelint:
      code:
        files:
          src: ['lib/*.coffee', 'spec/*.coffee']
        options:
          max_line_length:
            value: 100
            level: 'warn'
          no_trailing_semicolons:
            level: 'warn'

    # TODO: Browser build

    exec:
        microflo_emscripten: microflo "build-emscripten"

    mochaTest:
      nodejs:
        src: ['spec/*.coffee']
        options:
          reporter: 'spec'
          require: 'coffee-script/register'
          grep: process.env.TESTS

  # Grunt plugins used for building
  @loadNpmTasks 'grunt-exec'

  # Grunt plugins used for testing
  @loadNpmTasks 'grunt-mocha-test'

  # Our local tasks
  @registerTask 'build', [
    'exec:microflo_emscripten'
  ]

  @registerTask 'test', [
    'build'
    'mochaTest'
  ]

  @registerTask 'default', ['test']

Grunt: Fix options passed to microflo-emscripten


describe "Lanes.Models.Collection", ->

    it "it triggers promise on loading", (done) ->
        Model = Lanes.Test.defineModel
            props: { id: 'integer', title: 'string' }

        LT.syncSucceedWith([
            { id: 1, title: 'first value'  }
            { id: 2, title: 'second value' }
        ])
        collection = Model.where(name: 'foo')
        expect(collection.requestInProgress).toBeDefined()
        collection.whenLoaded ->
            expect( collection.isLoaded() ).toBe(true)
            done()

    it "triggers length when changed", ->
        Model = Lanes.Test.defineModel
            props: { id: 'integer', title: 'string' }

        collection = new Model.Collection
        spy = jasmine.createSpy('onLengthChange')
        collection.on("change:length", spy)
        model = collection.add({ id: 1, title: 'first' })
        expect(spy).toHaveBeenCalled()
        spy.calls.reset()
        collection.remove(model)
        expect(spy).toHaveBeenCalled()
        spy.calls.reset()
        collection.reset([{ id:11, title: 'last'}])
        expect(spy).toHaveBeenCalled()

    it 'prevents duplicates when copying from', ->
        Model = Lanes.Test.defineModel
            props: { id: 'integer', title: 'string' }
        collection = new Model.Collection
        a = collection.add({ id: 1, title: 'first'  })
        b = collection.add({ id: 2, title: 'second' })
        c = collection.add({ id: 3, title: 'third'  })
        a.copyFrom(c)
        expect(collection.pluck('id')).toEqual([2, 3, 1])

Test duplicate prevention when copying

Test duplicate prevention when copying


module.exports =
  configDefaults:
    showOnRightSideOfStatusBar: false

  activate: ->
    atom.workspaceView.command('grammar-selector:show', createGrammarListView)
    atom.packages.once('activated', createGrammarStatusView)

createGrammarListView = ->
  editor = atom.workspace.getActiveEditor()
  if editor?
    GrammarListView = require './grammar-list-view'
    view = new GrammarListView(editor)
    view.attach()

createGrammarStatusView = ->
  {statusBar} = atom.workspaceView
  if statusBar?
    GrammarStatusView = require './grammar-status-view'
    view = new GrammarStatusView(statusBar)
    view.attach()

module.exports =
  configDefaults:
    showOnRightSideOfStatusBar: true

  activate: ->
    atom.workspaceView.command('grammar-selector:show', createGrammarListView)
    atom.packages.once('activated', createGrammarStatusView)

createGrammarListView = ->
  editor = atom.workspace.getActiveEditor()
  if editor?
    GrammarListView = require './grammar-list-view'
    view = new GrammarListView(editor)
    view.attach()

createGrammarStatusView = ->
  {statusBar} = atom.workspaceView
  if statusBar?
    GrammarStatusView = require './grammar-status-view'
    view = new GrammarStatusView(statusBar)
    view.attach()

Put grammar selector on the right side by default

This will make it play nicer with showing more information after the
character position on the left side such as the character count.

Refs atom/status-bar#31


kd   = require 'kd'

nick    = require 'app/util/nick'
Tracker = require 'app/util/tracker'

module.exports = (machine) ->

  return  unless analytics
  return  unless typeof analytics.user is 'function'

  { initialTurnOn } = analytics.user().traits()
  return  if initialTurnOn

  initialTurnOn = yes
  analytics.identify nick(), { initialTurnOn }
  execute machine

execute = (machine) ->

  track Tracker.BUTTON_CLICKED

  kd.singletons.computeController.once 'MachineBuilt', (event) ->

    { machineId } = event

    return  if machineId isnt machine._id

    track Tracker.MODAL_DISPLAYED

track = (action) ->
  Tracker.track action, { category: Tracker.CATEGORY_TURN_ON_VM }

kd   = require 'kd'

nick    = require 'app/util/nick'
Tracker = require 'app/util/tracker'

module.exports = (machine) ->

  fetchStorage (storage) ->

    turnedOnMachine = storage.getValue 'TurnedOnMachine'

    return  if turnedOnMachine

    storage.setValue 'TurnedOnMachine', yes
    execute machine

fetchStorage = (callback) ->

  { appStorageController } = kd.singletons
  storage = appStorageController.storage 'Environments', '1.0'

  storage.ready -> callback storage

execute = (machine) ->

  track Tracker.BUTTON_CLICKED

  kd.singletons.computeController.once 'MachineBuilt', (event) ->

    { machineId } = event

    return  if machineId isnt machine._id

    track Tracker.MODAL_DISPLAYED

track = (action) ->
  Tracker.track action, { category: Tracker.CATEGORY_TURN_ON_VM }

Store initial machine turn on state in AppStorage


Q = require 'q'

# Provides a set of methods for voting data CRUD operations
class API
  constructor: (@db) ->
    throw "must provide db connection" unless @db

  createUser: (name) ->
    # Q.nfcall(
    #   @db.models.User.create,
    #   name: name
    # )

    # @db.models.User.create({
      # name: name
    # }, (err, user) ->

    deferred = Q.defer()
    user = new @db.models.User({name: name})
    user.save (err) ->
      if err
        deferred.reject(new Error(err))
      else
        deferred.resolve(user)

    deferred.promise

  incrementVote: ->

  decrementVote: (voteId) ->

  listUsers: (userId) ->

module.exports = API

Q = require 'q'

# Provides a set of methods for voting data CRUD operations
class API
  constructor: (@db) ->
    throw "must provide db connection" unless @db
    @models = @db.models

  createUser: (name) ->
    create = Q.nbind(
      @models.User.create,
      @models.User
    )
    create name: name

  incrementVote: ->

  decrementVote: (voteId) ->

  listUsers: (userId) ->

module.exports = API

Use Q nbind to make this cleaner

Use Q nbind to make this cleaner


{toggleQuotes} = require 'toggle-quotes'
{CompositeDisposable} = require 'atom'

module.exports =
  config:
    quoteCharacters:
      type: 'string'
      default: '"\''

  activate: ->
    @subscriptions.add atom.commands.add 'atom-text-editor', 'toggle-quotes:toggle', ->
      if editor = atom.workspace.getActiveTextEditor()
        toggleQuotes(editor)

  deactivate: ->
    @subscriptions.dispose()

{toggleQuotes} = require 'toggle-quotes'

module.exports =
  config:
    quoteCharacters:
      type: 'string'
      default: '"\''

  activate: ->
    @subscription = atom.commands.add 'atom-text-editor', 'toggle-quotes:toggle', ->
      if editor = atom.workspace.getActiveTextEditor()
        toggleQuotes(editor)

  deactivate: ->
    @subscription.dispose()

Use disposable returned from atom.commands.add


# tool tips

d3panels.tooltip_create = (selection, options) ->
    selection.append("div")
             .attr("class", "d3panels-tooltip")
             .style("opacity", 0)

d3panels.tooltip_activate = (objects, tipdiv, options) ->
    objects.on("mouseover", (d) ->
          tipdiv.html(d.tooltip)

          h = tipdiv.node().getBoundingClientRect().height

          tipdiv.style("left", (d3.event.pageX + d.r*3)+"px")
                .style("top", (d3.event.pageY - h/2)+"px")
                .transition()
                .duration(0)
                .style("opacity", 0.9))

    objects.on("mouseout", (d) ->
              tipdiv.transition()
                  .duration(1000)
                  .style("opacity", 0))

d3panels.tooltip_destroy = (tipdiv) ->
    tipdiv.remove()

# tool tips

d3panels.tooltip_create = (selection, options) ->
    d3.select("body").append("div")
             .attr("class", "d3panels-tooltip #{options.tipclass}")
             .style("opacity", 1)

d3panels.tooltip_activate = (objects, tipdiv, options, tooltip_func) ->
    objects.on("mouseover.d3panels-tooltip", (d,i) ->
          mouseX = d3.event.pageX
          mouseY = d3.event.pageY

          tipdiv.html(tooltip_func(d,i))

          tipbox_height = tipdiv.node().getBoundingClientRect().height

          tipdiv.style("left", "#{(mouseX + 10)}px")
                .style("top", "#{(mouseY - tipbox_height/2)}px")
                .transition()
                .duration(0)
                .style("opacity", 0.9))

    objects.on("mouseout.d3panels-tooltip", (d) ->
              tipdiv.transition()
                  .duration(1000)
                  .style("opacity", 0))

d3panels.tooltip_destroy = (tipdiv) ->
    tipdiv.remove()

Fix problems with initial tooltip code

Fix problems with initial tooltip code


avatarResponder = require('./avatar_responder')
Campfire.Transcript.messageTemplates = require('./message_templates')

window.Chicisimo =
  Responders: []

Campfire.USER_ACTIONS = ['enter','leave','kick','conference_created','lock','unlock','topic_change','allow_guests','disallow_guests']

swizzle(Campfire.Message, {
  authorElement: ($super) ->
    return $super().select('span.author')[0] if Campfire.USER_ACTIONS.include(this.kind)
    $super()
})

Campfire.Chicisimo = Class.create({
  initialize: (chat) ->
    chat.transcript.messages.forEach(this.executeResponders)

    chat.layoutmanager.layout()

    chat.windowmanager.scrollToBottom()
  ,onMessagesInserted: (messages) ->
    scrolledToBottom = chat.windowmanager.isScrolledToBottom()

    messages.forEach(this.executeResponders)

    chat.windowmanager.scrollToBottom() if scrolledToBottom
  ,executeResponders: (message) ->
    Chicisimo.Responders.forEach((responder) -> responder(message) )
})

Chicisimo.Responders.push(avatarResponder)
Campfire.Responders.push("Chicisimo")
window.chat.installPropaneResponder("Chicisimo", "chicisimo")

avatarResponder = require('./avatar_responder')
Campfire.Transcript.messageTemplates = require('./message_templates')

window.Chicisimo =
  Responders: []

Campfire.USER_ACTIONS = ['enter','leave','kick','conference_created','lock','unlock','topic_change','allow_guests','disallow_guests']

swizzle(Campfire.Message, {
  authorElement: ($super) ->
    return $super().select('span.author')[0] if Campfire.USER_ACTIONS.include(this.kind)
    $super()
})

Campfire.Chicisimo = Class.create(
  initialize: (chat) ->
    chat.transcript.messages.forEach(this.executeResponders)

    chat.layoutmanager.layout()

    chat.windowmanager.scrollToBottom()
  ,onMessagesInserted: (messages) ->
    scrolledToBottom = chat.windowmanager.isScrolledToBottom()

    messages.forEach(this.executeResponders)

    chat.windowmanager.scrollToBottom() if scrolledToBottom
  ,executeResponders: (message) ->
    Chicisimo.Responders.forEach((responder) -> responder(message))
)

Chicisimo.Responders.push(avatarResponder)
Campfire.Responders.push("Chicisimo")
window.chat.installPropaneResponder("Chicisimo", "chicisimo")

Remove whitespace and unnecessary parens


angular.module('admin.payments').directive "stripeElements", ($injector, AdminStripeElements) ->
  restrict: 'E'
  template: "\

\

\
             "
  scope:
    selected: "="

  link: (scope, elem, attr)->
    if $injector.has('stripeObject')
      stripe = $injector.get('stripeObject')

      card = stripe.elements().create 'card',
        hidePostalCode: false
        style:
          base:
            fontFamily: "Roboto, Arial, sans-serif"
            fontSize: '16px'
            color: '#5c5c5c'
            '::placeholder':
              color: '#6c6c6c'
      card.mount(elem.find('.card-element').get(0))

      # Elements validates user input as it is typed. To help your customers
      # catch mistakes, you should listen to change events on the card Element
      # and display any errors:
      card.addEventListener 'change', (event) ->
        displayError = elem.find('.card-errors').get(0)
        if event.error
          displayError.textContent = event.error.message
        else
          displayError.textContent = ''

        return

      scope.$watch "selected", (value) ->
        if (value)
          AdminStripeElements.stripe = stripe
          AdminStripeElements.card = card

angular.module('admin.payments').directive "stripeElements", ($injector, AdminStripeElements) ->
  restrict: 'E'
  template: "
\

\

\

"
  scope:
    selected: "="

  link: (scope, elem, attr)->
    if $injector.has('stripeObject')
      stripe = $injector.get('stripeObject')

      card = stripe.elements().create 'card',
        hidePostalCode: false
        style:
          base:
            fontFamily: "Roboto, Arial, sans-serif"
            fontSize: '16px'
            color: '#5c5c5c'
            '::placeholder':
              color: '#6c6c6c'
      card.mount(elem.find('.card-element').get(0))

      # Elements validates user input as it is typed. To help your customers
      # catch mistakes, you should listen to change events on the card Element
      # and display any errors:
      card.addEventListener 'change', (event) ->
        displayError = elem.find('.card-errors').get(0)
        if event.error
          displayError.textContent = event.error.message
        else
          displayError.textContent = ''

        return

      scope.$watch "selected", (value) ->
        if (value)
          AdminStripeElements.stripe = stripe
          AdminStripeElements.card = card

Remove id "card-element" as well

Remove id "card-element" as well


'name': 'Weave.jl markdown'
scopeName: 'source.weave.md'
'fileTypes': [
  'jmd'
  'jmdw'
  'mdw'
]
patterns: [
    {
      'include' : 'source.weave.noweb'
    }
    {
    'begin': '^([`~]{3,})(\\{|\\{\\.|)(julia)(;|)\\s*(.*?)(\\}|)\\s*$'
    'beginCaptures':
      '1':
        'name': 'markup.heading.weave.md'
      '3':
        'name': 'markup.bold.weave.md'
      '5':
        'contentName' : 'source.embedded.julia'
        'patterns': [
          {
            'include': 'source.julia'
          }
        ]
    'end': '^[`~]{3,}\\s*$'
    'endCaptures':
      '0':
        'name': 'markup.heading.weave.md'
    'contentName': 'source.embedded.julia'
    'patterns': [
      {
        'include': 'source.julia'
      }
    ]
    }
    {
      'include': 'source.gfm'
    }
    {
      'include': 'text.md'
    }
]

'name': 'Weave.jl markdown'
'scopeName' : 'source.weave.md'
'fileTypes': [
  'jmd'
  'jmdw'
  'mdw'
]
'patterns': [
    {
      'include' : 'source.weave.noweb'
    }
    {
    'begin': '^([`~]{3,})(\\{|\\{\\.|)(julia)(;|)\\s*(.*?)(\\}|)\\s*$'
    'beginCaptures':
      '1':
        'name': 'markup.heading.weave.md'
      '3':
        'name': 'markup.bold.weave.md'
      '5':
        'contentName' : 'source.embedded.julia'
        'patterns': [
          {
            'include': 'source.julia'
          }
        ]
    'end': '^[`~]{3,}\\s*$'
    'endCaptures':
      '0':
        'name': 'markup.heading.weave.md'
    'contentName': 'source.embedded.julia'
    'patterns': [
      {
        'include': 'source.julia'
      }
    ]
    }
    {
      'begin' : '^(!)\\s(.*)'
      'beginCaptures':
        '1' :
            'name' : 'markup.bold.weave.md'
        '2':
          'contentName': 'source.embedded.julia'
          'patterns' : [
                  {
                    'include': 'source.julia'
                  }
                ]
      'end' : '$'
    }
    {
      'include': 'source.gfm'
    }
    {
      'include': 'text.md'
    }
]

Add support for new inline code format

Add support for new inline code format


Link = require('react-router').Link

module.exports = React.createClass
  displayName: 'HelloWorld'
  render: ->

Hello world!

You're looking at the Coffeescript React Quickstart project by Kyle Mathews.

It has a number of nice goodies included like:

Full Coffeescript support provided by coffee-react-transform

Live reloading for both CSS and Javascript! This really speeds up your development. Live reload of Javascript enabled by the react-hot-loader project.

Gulpfile with both development and production tasks to simplify building your project.

Starter Sass project with sensible defaults. Check them out on the <Link to="styleguide">styleguide page</Link>

Link = require('react-router').Link

module.exports = React.createClass
  displayName: 'HelloWorld'
  render: ->

Hello world!

You're looking at the Coffeescript React Quickstart project by Kyle Mathews.

It has a number of nice goodies included like:

Live reloading for both CSS and Javascript! This really speeds up your development. Live reloading is powered by the Webpack module bundler and the react-hot-loader projects.

Full Coffeescript for React support provided by coffee-react-transform

Amazing URL-driven-development (UDD) with the react-router project

Uses Gulp for building CSS and Javascript. Run `cult watch` for rebuilding css/js on the fly while developing and `cult build` to create minified versions to deploy to production.

Starter Sass project with sensible defaults. Check them out on the <Link to="styleguide">styleguide page</Link>

Uses the best of breed grid system Susy.

Add list of 'batteries included' for demo page


Species.TaxonConceptDocumentsRoute = Ember.Route.extend
  renderTemplate: ->
    @getDocuments()
    @render('taxon_concept/documents')

  getDocuments: ->
    model = this.modelFor("taxonConcept")
    $.ajax(
      url: "/api/v1/documents?taxon_concept_id=" + model.get('id'),
      success: (data) ->
        model.set('cites_cop_docs', data.cites_cop_docs)
        model.set('ec_srg_docs', data.ec_srg_docs)
        model.set('cites_ac_docs', data.cites_ac_docs)
        model.set('cites_pc_docs', data.cites_pc_docs)
        model.set('other_docs', data.other_docs)
      error: (jqXHR, textStatus, errorThrown) ->
        console.log("AJAX Error:" + textStatus)
    )

Species.TaxonConceptDocumentsRoute = Ember.Route.extend
  renderTemplate: ->
    @getDocuments()
    @render('taxon_concept/documents')

  getDocuments: ->
    model = this.modelFor("taxonConcept")
    $.ajax(
      url: "/api/v1/documents?taxon-concepts-ids=" + model.get('id'),
      success: (data) ->
        model.set('cites_cop_docs', data.cites_cop_docs)
        model.set('ec_srg_docs', data.ec_srg_docs)
        model.set('cites_ac_docs', data.cites_ac_docs)
        model.set('cites_pc_docs', data.cites_pc_docs)
        model.set('other_docs', data.other_docs)
      error: (jqXHR, textStatus, errorThrown) ->
        console.log("AJAX Error:" + textStatus)
    )

Update document search usage in taxon concept's page


class Workbench.Views.SensorMapView extends Backbone.Marionette.ItemView
  template: false

  initialize: ->
    @zoom = 13

  onDestroy: ->
    @map.remove() if @map

  onShow: ->
    if @el.id is ""
      console.warn "No Map Element"
    else
      @location = [@model.get("latitude"), @model.get("longitude")]
      @map = L.map(@el.id).setView(@location, @zoom)
      L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
        attribution: t('map.attribution')
      }).addTo(@map)

      L.marker(@location).addTo(@map)

class Workbench.Views.SensorMapView extends Backbone.Marionette.ItemView
  template: false

  initialize: ->
    @zoom = 13

  onDestroy: ->
    @map.remove() if @map

  onShow: ->
    if @el.id is ""
      console.warn "No Map Element"
    else
      @location = [@model.get("latitude"), @model.get("longitude")]
      @map = L.map(@el.id).setView(@location, @zoom)
      L.tileLayer(Workbench.tile_url, {
        attribution: Workbench.tile_attribution
      }).addTo(@map)

      L.marker(@location).addTo(@map)

Use master map tile selection for sensor map


module.exports =
class BroadcastTarget
  editor: null
  listener: null
  isMarkdownPreview: false

  constructor: ->
    @editor = atom.workspace.activePaneItem

    @isMarkdownPreview = @editor[0]?

    @editor.on 'markdown-preview:markdown-changed', =>
      @listener?()

  setListener: (listener) ->
    @listener = listener

  getContent: ->
    return if @isMarkdownPreview then @getMarkdownPreviewContent() else @getOtherContent()

  getMarkdownPreviewContent: ->
    content = @editor[0].outerHTML
    if atom.config.get 'broadcast.getEmojisFromCheatSheetSite'
      content = content.replace /[\w-\.\/]+pngs/g, @urlToCheatSheetSite
    else
      content = content.replace /[\w-\.\/]+node_modules\/roaster\/node_modules/g, ''

  getOtherContent: ->
    content = @editor.getText?()
    return '<pre>' + content + '</pre>'

module.exports =
class BroadcastTarget
  editor: null
  listener: null
  isMarkdownPreview: false

  constructor: ->
    @editor = atom.workspace.activePaneItem

    @isMarkdownPreview = @editor[0]?

    @editor.on 'markdown-preview:markdown-changed', =>
      @listener?()

  setListener: (listener) ->
    @listener = listener

  getContent: ->
    return if @isMarkdownPreview then @getMarkdownPreviewContent() else @getOtherContent()

  getMarkdownPreviewContent: ->
    content = @editor[0].outerHTML
    if atom.config.get 'broadcast.getEmojisFromCheatSheetSite'
      content = content.replace /[\w-\.\/]+pngs/g, @urlToCheatSheetSite
    else
      content = content.replace /[\w-\.\/]+node_modules\/roaster\/node_modules/g, ''

  getOtherContent: ->
    content = @editor.getText?()
    .replace /</g, '<'
    .replace />/g, '>'

    return '<pre>' + content + '</pre>'

Fix an issue that '<' and '>' were not shown correctly


'exception-reporting':
  'userId': 'ee24cf00-f793-9081-be2a-2cdae5536b7f'
'release-notes':
  'viewedVersion': '0.64.0'
'welcome':
  'showOnStartup': false
'metrics':
  'userId': '51eeb6113c1ae801c9aade9b6d679aa5189ced25'
'editor':
  'fontFamily': 'Source Code Pro'
  'fontSize': 14
  'preferredLineLength': 100
  'showInvisibles': true
'core':
  'projectHome': '/Volumes/Data/Users/Lee/Source'
  'themes': [
    'atom-dark-ui'
    'railscasts-syntax'
  ]
  'ignoredNames': [
    '.git'
    '.svn'
    '.DS_Store'
  ]
  'disabledPackages': []
'whitespace':
  'ensureSingleTrailingNewline': true
'auto-copyright':
  'owner': 'Lifted Studios'
'spell-check':
  'grammars': [
    'source.gfm'
    'text.git-commit'
    'text.plain'
  ]

Add selectors for spell checking.

Add selectors for spell checking.


"*":
  core:
    telemetryConsent: "limited"
    themes: [
      "one-light-ui"
      "one-light-syntax"
    ]
  editor:
    fontFamily: "'SF Mono', Menlo, Consolas, DejaVu Sans Mono, monospace"
    fontSize: 12
    lineHeight: 1.7
  "one-dark-ui":
    tabCloseButton: "Left"
  "one-light-ui":
    tabCloseButton: "Left"

"*":
  core:
    disabledPackages: [
      "exception-reporting"
    ]
    telemetryConsent: "limited"
    themes: [
      "one-light-ui"
      "one-light-syntax"
    ]
  editor:
    fontFamily: "'SF Mono', Menlo, Consolas, DejaVu Sans Mono, monospace"
    fontSize: 12
    lineHeight: 1.7
  "one-dark-ui":
    tabCloseButton: "Left"
  "one-light-ui":
    tabCloseButton: "Left"

Disable 'exceptino-reporting' so userId GUID isn’t checked in


globals = require 'globals'

module.exports =

  getOperation : (current, selected) ->

    arr = [
      @planTitle.FREE
      @planTitle.HOBBYIST
      @planTitle.DEVELOPER
      @planTitle.PROFESSIONAL
    ]

    current  = arr.indexOf current
    selected = arr.indexOf selected

    return switch
      when selected >  current then @operation.UPGRADE
      when selected is current then @operation.INTERVAL_CHANGE
      when selected <  current then @operation.DOWNGRADE

  planInterval:
    MONTH       : 'month'
    YEAR        : 'year'

  planTitle:
    FREE         : 'free'
    HOBBYIST     : 'hobbyist'
    DEVELOPER    : 'developer'
    PROFESSIONAL : 'professional'

  provider:
    STRIPE : 'stripe'
    PAYPAL : 'paypal'
    KODING : 'koding'

  operation:
    UPGRADE         : 1
    INTERVAL_CHANGE : 0
    DOWNGRADE       : -1

  FAILED_ATTEMPT_LIMIT: 3
  TOO_MANY_ATTEMPT_BLOCK_KEY: 'BlockForTooManyAttempts'
  TOO_MANY_ATTEMPT_BLOCK_DURATION: globals.config.paymentBlockDuration

  error:
    ERR_USER_NOT_CONFIRMED: 'You need to confirm your email to purchase a Koding subscription.'

  events:
    WORKFLOW_STARTED: 'workflowStarted'
    WORKFLOW_COULD_NOT_START: 'workflowCouldNotStart'

globals = require 'globals'

module.exports =

  getOperation : (current, selected) ->

    arr = [
      @planTitle.FREE
      @planTitle.HOBBYIST
      @planTitle.DEVELOPER
      @planTitle.PROFESSIONAL
    ]

    current  = arr.indexOf current
    selected = arr.indexOf selected

    return switch
      when selected >  current then @operation.UPGRADE
      when selected is current then @operation.INTERVAL_CHANGE
      when selected <  current then @operation.DOWNGRADE

  planInterval:
    MONTH       : 'month'
    YEAR        : 'year'

  planTitle:
    FREE         : 'free'
    HOBBYIST     : 'hobbyist'
    DEVELOPER    : 'developer'
    PROFESSIONAL : 'professional'

  provider:
    STRIPE : 'stripe'
    PAYPAL : 'paypal'
    KODING : 'koding'

  operation:
    UPGRADE         : 1
    INTERVAL_CHANGE : 0
    DOWNGRADE       : -1

  FAILED_ATTEMPT_LIMIT: 3
  TOO_MANY_ATTEMPT_BLOCK_KEY: 'BlockForTooManyAttempts'
  TOO_MANY_ATTEMPT_BLOCK_DURATION: globals.config.paymentBlockDuration

  error:
    ERR_USER_NOT_CONFIRMED: 'You need to confirm your email to purchase a Koding subscription.'

  events:
    WORKFLOW_STARTED: 'WorkflowStarted'
    WORKFLOW_COULD_NOT_START: 'WorkflowCouldNotStart'

Change camel case event names.

Change camel case event names.


"*":
  "exception-reporting":
    userId: "30e6f2d0-42d3-ab77-4984-dde4c431f019"
  welcome:
    showOnStartup: false
  core: {}
  editor:
    invisibles: {}
    fontFamily: "Hack"
  autosave:
    enabled: true
  "git-diff":
    showIconsInEditorGutter: true
  "ruby-test":
    testFramework: "minitest"
    rspecAllCommand: "vagrant ssh -c \"rspec --tty spec\""
    rspecFileCommand: "vagrant ssh -c \"rspec --tty {relative_path}\""
    rspecSingleCommand: "vagrant ssh -c \"rspec --tty {relative_path}:{line_number}\""
  "git-blame": {}

"*":
  "exception-reporting":
    userId: "30e6f2d0-42d3-ab77-4984-dde4c431f019"
  welcome:
    showOnStartup: false
  core:
    projectHome: "/Users/randy/src"
    audioBeep: false
  editor:
    invisibles: {}
    fontFamily: "Hack"
    preferredLineLength: 100
    showIndentGuide: true
  autosave:
    enabled: true
  "git-diff":
    showIconsInEditorGutter: true
  "ruby-test":
    testFramework: "minitest"
    rspecAllCommand: "vagrant ssh -c \"rspec --tty spec\""
    rspecFileCommand: "vagrant ssh -c \"rspec --tty {relative_path}\""
    rspecSingleCommand: "vagrant ssh -c \"rspec --tty {relative_path}:{line_number}\""
  "git-blame": {}

Tweak a few Atom settings

Tweak a few Atom settings


React = require 'react'
ReactDOM = {render} = require 'react-dom'
{Router, Route, Link} = require 'react-router'
createBrowserHistory = require 'history/lib/createBrowserHistory'
routes = require './router'

routes = require './router'
history = createBrowserHistory()

if process.env.NON_ROOT isnt 'true' and window.location? and window.location.hash isnt ""
  window.location.pathname = window.location.hash.slice(1)

history.listen (location) ->
  window.dispatchEvent new CustomEvent 'locationchange'

location = if process.env.NON_ROOT == "true"
    null
  else
    Router.HistoryLocation

render <Router history={history}>{routes}</Router>,
  document.getElementById('panoptes-main-container')

logDeployedCommit = require './lib/log-deployed-commit'
logDeployedCommit()

React = require 'react'
ReactDOM = {render} = require 'react-dom'
{Router, Route, Link} = require 'react-router'
{useBasename} = require 'history'
createBrowserHistory = require 'history/lib/createBrowserHistory'
routes = require './router'

routes = require './router'

basename = if process.env.DEPLOY_SUBDIR? then "/panoptes-front-end/#{process.env.DEPLOY_SUBDIR}/" else ''

history = useBasename(createBrowserHistory)({basename})

if process.env.NON_ROOT isnt 'true' and window.location? and window.location.hash isnt ""
  window.location.pathname = window.location.hash.slice(1)

history.listen (location) ->
  window.dispatchEvent new CustomEvent 'locationchange'

location = if process.env.NON_ROOT == "true"
    null
  else
    Router.HistoryLocation

render <Router history={history}>{routes}</Router>,
  document.getElementById('panoptes-main-container')

logDeployedCommit = require './lib/log-deployed-commit'
logDeployedCommit()

Add basename to history for subdirectory deploys


{$$} = require 'space-pen'
SelectList = require 'select-list'
$ = require 'jquery'
_ = require 'underscore'

module.exports =
class CommandPaletteView extends SelectList
  @activate: (rootView) ->
    @instance = new CommandPaletteView(rootView)

  @viewClass: ->
    "#{super} command-palette"

  filterKey: 'eventDescription'

  previouslyFocusedElement: null
  keyBindings: null

  initialize: (@rootView) ->
    @command 'command-palette:toggle', =>
      @cancel()
      false
    super

  attach: ->
    super

    @keyBindings = _.losslessInvert(keymap.bindingsForElement(@previouslyFocusedElement))

    events = []
    for eventName, eventDescription of _.extend($(window).events(), @previouslyFocusedElement.events())
      events.push({eventName, eventDescription}) if eventDescription

    events = _.sortBy events, (e) -> e.eventDescription

    @setArray(events)
    @appendTo(@rootView)
    @miniEditor.setText('')
    @miniEditor.focus()

  itemForElement: ({eventName, eventDescription}) ->
    keyBindings = @keyBindings
    $$ ->
      @li class: 'event', 'data-event-name': eventName, =>
        @div eventDescription, class: 'event-description'
        @div class: 'right', =>
          @div eventName, class: 'event-name'
          for binding in keyBindings[eventName] ? []
            @div binding, class: 'key-binding'
        @div class: 'clear-float'

  confirmed: ({eventName}) ->
    @cancel()
    @previouslyFocusedElement.trigger(eventName)

  cancelled: ->

{$$} = require 'space-pen'
SelectList = require 'select-list'
$ = require 'jquery'
_ = require 'underscore'

module.exports =
class CommandPaletteView extends SelectList
  @activate: (rootView) ->
    @instance = new CommandPaletteView(rootView)

  @viewClass: ->
    "#{super} command-palette"

  filterKey: 'eventDescription'

  previouslyFocusedElement: null
  keyBindings: null

  initialize: (@rootView) ->
    @command 'command-palette:toggle', =>
      @cancel()
      false
    super

  attach: ->
    super

    @keyBindings = _.losslessInvert(keymap.bindingsForElement(@previouslyFocusedElement))

    events = []
    for eventName, eventDescription of _.extend($(window).events(), @previouslyFocusedElement.events())
      events.push({eventName, eventDescription}) if eventDescription

    events = _.sortBy events, (e) -> e.eventDescription

    @setArray(events)
    @appendTo(@rootView)
    @miniEditor.focus()

  itemForElement: ({eventName, eventDescription}) ->
    keyBindings = @keyBindings
    $$ ->
      @li class: 'event', 'data-event-name': eventName, =>
        @div eventDescription, class: 'event-description'
        @div class: 'right', =>
          @div eventName, class: 'event-name'
          for binding in keyBindings[eventName] ? []
            @div binding, class: 'key-binding'
        @div class: 'clear-float'

  confirmed: ({eventName}) ->
    @cancel()
    @previouslyFocusedElement.trigger(eventName)

Clear mini editor base select list cancelled()

Clearing the mini editor when closing is something
all sub-classes were already doing so it makes sense
to pull it up to the base class as the default
cancelled() implementation that can still be overridden
if needed.


module.exports = (grunt) ->
  grunt.initConfig
    pkg: grunt.file.readJSON('package.json')

    coffee:
      glob_to_multiple:
        expand: true
        cwd: 'src'
        src: ['*.coffee']
        dest: 'lib'
        ext: '.js'

    coffeelint:
      options:
        max_line_length:
          level: 'ignore'

      src: ['src/**/*.coffee']
      test: ['spec/**/*.coffee']

    cpplint:
      files: ['src/**/*.cc']
      reporter: 'spec'
      verbosity: 1
      filters:
        build:
          include: false
          namespaces: false
        legal:
          copyright: false
        readability:
          braces: false

    shell:
      rebuild:
        command: 'npm build .'
        options:
          stdout: true
          stderr: true
          failOnError: true

      test:
        command: 'jasmine-focused --captureExceptions --coffee spec/'
        options:
          stdout: true
          stderr: true
          failOnError: true

  grunt.loadNpmTasks('grunt-contrib-coffee')
  grunt.loadNpmTasks('grunt-shell')
  grunt.loadNpmTasks('grunt-coffeelint')
  grunt.loadNpmTasks('node-cpplint')
  grunt.registerTask('lint', ['coffeelint', 'cpplint'])
  grunt.registerTask('default', ['lint', 'coffee', 'shell:rebuild'])
  grunt.registerTask('test', ['default', 'shell:test'])
  grunt.registerTask 'clean', ->
    rm = require('rimraf').sync
    rm('lib')
    rm('build')

module.exports = (grunt) ->
  grunt.initConfig
    pkg: grunt.file.readJSON('package.json')

    coffee:
      glob_to_multiple:
        expand: true
        cwd: 'src'
        src: ['*.coffee']
        dest: 'lib'
        ext: '.js'

    coffeelint:
      options:
        max_line_length:
          level: 'ignore'

      src: ['src/**/*.coffee']
      test: ['spec/**/*.coffee']

    cpplint:
      files: ['src/**/*.cc']
      reporter: 'spec'
      verbosity: 1
      filters:
        build:
          include: false
          namespaces: false
        legal:
          copyright: false
        readability:
          braces: false

    shell:
      rebuild:
        command: 'npm build .'
        options:
          stdout: true
          stderr: true
          failOnError: true

      test:
        command: 'node node_modules/jasmine-focused/bin/jasmine-focused --captureExceptions --coffee spec/'
        options:
          stdout: true
          stderr: true
          failOnError: true

  grunt.loadNpmTasks('grunt-contrib-coffee')
  grunt.loadNpmTasks('grunt-shell')
  grunt.loadNpmTasks('grunt-coffeelint')
  grunt.loadNpmTasks('node-cpplint')
  grunt.registerTask('lint', ['coffeelint', 'cpplint'])
  grunt.registerTask('default', ['lint', 'coffee', 'shell:rebuild'])
  grunt.registerTask('test', ['default', 'shell:test'])
  grunt.registerTask 'clean', ->
    rm = require('rimraf').sync
    rm('lib')
    rm('build')

Fix running specs on Windows.

Fix running specs on Windows.


_         = require 'underscore'
sd        = require('sharify').data
Backbone  = require 'backbone'

Artworks            = require '../../../collections/artworks.coffee'
LayeredSearchView   = require('./layered-search.coffee').LayeredSearchView
SaleView            = require './sale.coffee'

module.exports = class BelowTheFold extends Backbone.View
  initialize: (options) ->
    { @saved, @artwork } = options

    $.when.apply(null, @artwork.fetchRelatedCollections()).then =>
      # Find the first related collection that has any results
      availableFeature = _.find @artwork.relatedCollections, (xs) -> xs.length
      if availableFeature
        @["setup#{availableFeature.kind}"]()
      else
        # Always fallback to layered search if there are no features available
        @setupLayeredSearch()

  setupLayeredSearch: ->
    new LayeredSearchView el: @$el, artwork: @artwork
    @done()

  setupSales: ->
    new SaleView el: @$el, sale: @artwork.sales.first(), saved: @saved
    @done()

  setupFairs: ->
    throw 'I don\'t know how to do this yet!'

  setupShows: ->
    throw 'I don\'t know how to do this yet!'

  done: ->
    @$el.attr 'data-state', 'fade-in'

_         = require 'underscore'
sd        = require('sharify').data
Backbone  = require 'backbone'

Artworks            = require '../../../collections/artworks.coffee'
LayeredSearchView   = require('./layered-search.coffee').LayeredSearchView
SaleView            = require './sale.coffee'

module.exports = class BelowTheFold extends Backbone.View
  initialize: (options) ->
    { @saved, @artwork } = options

    $.when.apply(null, @artwork.fetchRelatedCollections()).then =>
      # Find the first related collection that has any results
      @availableFeature = _.find @artwork.relatedCollections, (xs) -> xs.length
      if @availableFeature
        @["setup#{@availableFeature.kind}"]()
      else
        # Always fallback to layered search if there are no features available
        @setupLayeredSearch()

  setupLayeredSearch: (options = {}) ->
    { @fair } = options
    new LayeredSearchView el: @$el, artwork: @artwork, fair: @fair
    @done()

  setupSales: ->
    new SaleView el: @$el, sale: @artwork.sales.first(), saved: @saved
    @done()

  setupFairs: ->
    fair = @availableFeature.first()
    @setupLayeredSearch fair: fair

  setupShows: ->
    throw 'I don\'t know how to do this yet!'

  done: ->
    @$el.attr 'data-state', 'fade-in'

Enable the fair setup and pass in the fair to the layered search view


class PanelView extends HTMLElement
  constructor: ->
module.exports = PanelView

class PanelView extends HTMLElement
  constructor: ->
  registerModel: (Model)->
    @Model = Model
    @Model.View = this
  createdCallback: ->
    this.id = 'linter-panel'
  render: (Messages)->

module.exports = PanelView

Add basic methods to PanelView

:new: Add basic methods to PanelView


define (require) ->
  Backbone = require('backbone')
  settings = require('cs!settings')

  SEARCH_URI = "#{location.protocol}//#{settings.cnxarchive.host}:#{settings.cnxarchive.port}/search"

  return class SearchResults extends Backbone.Model
    url: () -> "#{SEARCH_URI}#{@query}"

    defaults:
      query:
        limits: []
        sort: []
      results:
        items: []
        total: 0

    initialize: (options = {}) ->
      @query = options.query or ''
      @fetch
        success: () => @set('loaded', true)

    parse: (response, options) ->
      response = super(arguments...)

      authors = new Backbone.Collection()
      _.each response.results.limits, (limit) ->
        if limit.author then authors.add(limit.author)

      _.each response.results.items, (item) ->
        _.each item.authors, (author, index) ->
          item.authors[index] = authors.get(author).toJSON()

      return response

define (require) ->
  Backbone = require('backbone')
  settings = require('cs!settings')

  SEARCH_URI = "#{location.protocol}//#{settings.cnxarchive.host}:#{settings.cnxarchive.port}/search"

  return class SearchResults extends Backbone.Model
    url: () -> "#{SEARCH_URI}#{@query}"

    defaults:
      query:
        limits: []
        sort: []
      results:
        items: []
        total: 0

    initialize: (options = {}) ->
      @query = options.query or ''
      @fetch
        success: () => @set('loaded', true)

    parse: (response, options) ->
      response = super(arguments...)

      authors = new Backbone.Collection()
      _.each response.results.limits, (limit) ->
        if limit.author then authors.add(limit.author)

      _.each response.results.items, (item) ->
        _.each item.authors, (author, index) ->
          item.authors[index] = authors.get(author).toJSON()

      #response.queryFormatted = _.cloneDeep(response.query)
      response.queryFormatted = JSON.parse(JSON.stringify(response.query)) # HACK to deep clone
      _.each response.queryFormatted.limits, (limit) ->
        if limit.authorID
          author = authors.get(limit.authorID).toJSON()
          limit.authorID = "#{author.fullname} (#{author.id})"

      return response

Format search query to display authorID with author's full name


#= require clipboard

$ ->
  clipboard = new Clipboard '.js-clipboard-trigger',
    text: (trigger) ->
      $target = $(trigger.nextElementSibling || trigger.previousElementSibling)
      $target.data('clipboard-text') || $target.text().trim()

  clipboard.on 'success', (e) ->
    $(e.trigger).
      tooltip(trigger: 'manual', placement: 'auto bottom', title: 'Copied!').
      tooltip('show')

    # Clear the selection and blur the trigger so it loses its border
    e.clearSelection()
    $(e.trigger).blur()

    # Manually hide the tooltip after 1 second
    setTimeout(->
      $(e.trigger).tooltip('hide')
    , 1000)

#= require clipboard

$ ->
  clipboard = new Clipboard '.js-clipboard-trigger',
    text: (trigger) ->
      $target = $(trigger.nextElementSibling || trigger.previousElementSibling)
      $target.data('clipboard-text') || $target.text().trim()

  clipboard.on 'success', (e) ->
    $(e.trigger).
      tooltip(trigger: 'manual', placement: 'auto bottom', title: 'Copied!').
      tooltip('show').
      one('mouseleave', -> $(this).tooltip('hide'))

    # Clear the selection and blur the trigger so it loses its border
    e.clearSelection()
    $(e.trigger).blur()

  # Safari doesn't support `execCommand`, so instead we inform the user to
  # copy manually.
  #
  # See http://clipboardjs.com/#browser-support
  clipboard.on 'error', (e) ->
    if /Mac/i.test(navigator.userAgent)
      title = "Press ⌘-C to copy"
    else
      title = "Press Ctrl-C to copy"

    $(e.trigger).
      tooltip(trigger: 'manual', placement: 'auto bottom', html: true, title: title).
      tooltip('show').
      one('mouseleave', -> $(this).tooltip('hide'))

Add a fallback for Safari copy-to-clipboard

Also, hide the tooltip in a less stupid way.

Closes #3547


".source.viml":
	editor:
		commentStart: '" '
		increaseIndentPattern: "(?:^|\\s)(?:if|else|elseif|for|function!?|while)(?:\\s|$)"
		decreaseIndentPattern: "(?:^|\\s)(?:endif|endfor|endfunction|endwhile)(?:\\s|$)"

Add editor settings for adjusting indent/outdent


$ ->

  $("#slider").slider
    value: 1
    min: 1
    max: 3
    slide: (event, ui) ->
      num = ui.value+1
      verbosity = while num -= 1 then 'v'
      $("#job_verbosity").val verbosity.join('')

  if $('#job-results').size() > 0

    div = $ '#job-results'
    project_id = div.data 'project_id'
    job_id = div.data 'job_id'

    get_job_status = ->
      $.getJSON "/projects/#{project_id}/jobs/#{job_id}", (data) ->
        if data.results == null
          setTimeout get_job_status, 3000
        else
          div.removeClass('hide').html data.results

          title = div.siblings('h3')
          title.find('img').remove()
          text = title.text().replace /Running/, 'Task'
          text = text.replace /\.\.\./, 'completed'
          title.text text

          $('.alert-message').remove()

          if data.success
            $('.tabs .pull-right').html 'SUCCESS'
          else
            $('.tabs .pull-right').html 'FAILED'

    setTimeout get_job_status, 3000

$ ->

  $("#slider").slider
    value: 3
    min: 1
    max: 3
    slide: (event, ui) ->
      num = ui.value+1
      verbosity = while num -= 1 then 'v'
      $("#job_verbosity").val verbosity.join('')

  if $('#job-results').size() > 0

    div = $ '#job-results'
    project_id = div.data 'project_id'
    job_id = div.data 'job_id'

    get_job_status = ->
      $.getJSON "/projects/#{project_id}/jobs/#{job_id}", (data) ->
        if data.results == null
          setTimeout get_job_status, 3000
        else
          div.removeClass('hide').html data.results

          title = div.siblings('h3')
          title.find('img').remove()
          text = title.text().replace /Running/, 'Task'
          text = text.replace /\.\.\./, 'completed'
          title.text text

          $('.alert-message').remove()

          if data.success
            $('.tabs .pull-right').html 'SUCCESS'
          else
            $('.tabs .pull-right').html 'FAILED'

    setTimeout get_job_status, 3000

Set default vebosity to 3

Set default vebosity to 3


$( ->

  $('a.pdf-languages-trigger').click ->
    $(this).toggleClass 'active'
    $('.download-languages').toggleClass 'active'

	categories = [
		{ href: '#tab-essentials-content', contentSelector: '.tab-essentials-content', anchorSelector: '[href="#tab-essentials-content"]' }
		{ href: '#tab-useful-content', contentSelector: '.tab-useful-content', anchorSelector: '[href="#tab-useful-content"]' }
		{ href: '#tab-personal-content', contentSelector: '.tab-personal-content', anchorSelector: '[href="#tab-personal-content"]' }
	]

	showActive categories

	window.onhashchange = -> showActive categories

)

categories = [
	{ href: '#tab-essentials-content', contentSelector: '.tab-essentials-content', anchorSelector: '[href="#tab-essentials-content"]' }
	{ href: '#tab-useful-content', contentSelector: '.tab-useful-content', anchorSelector: '[href="#tab-useful-content"]' }
	{ href: '#tab-personal-content', contentSelector: '.tab-personal-content', anchorSelector: '[href="#tab-personal-content"]' }
]

$(document).ready ->

  $('a.pdf-languages-trigger').click ->
    $(this).toggleClass 'active'
    $('.download-languages').toggleClass 'active'

  $('.tab-useful-content').hide()
  $('.tab-personal-content').hide()

	showActive categories

window.onhashchange = -> showActive categories

Hide useful and personal supplies when there's no hash in the url.


# Secure version of the ledger.storage.ChromeStore. This store uses AES encryption for storing keys and data
class @ledger.storage.SecureStore extends ledger.storage.ChromeStore

  # @param [String] name The store name
  # @param [String] key The secure key used to encrypt and decrypt data with AES
  constructor: (name, key) ->
    super(name)
    @_aes = new ledger.crypto.AES(key)
    @_hasCalledKeys = no
    @_keysCache = []

  # @see Store.keys
  keys: (cb) ->
    if @_hasCalledKeys
      _.defer => cb?(@_keysCache)
    else
      super (encrypted_keys) =>
        @_keysCache = _.uniq(@_keysCache.concat(_.compact(Try(=> @_aes.decrypt(encrypted_key)).orNull() for encrypted_key in encrypted_keys)))
        @_hasCalledKeys = yes
        cb?(@_keysCache)

  _preprocessKey: (key) -> super(@_aes.encrypt(key))
  _deprocessKey: (raw_key) ->
    key = Try(=> @_aes.decrypt(super(raw_key))).orNull()
    @_keysCache.push key unless _(@_keysCache).contains(key)
    key

  _preprocessValue: (value) -> Try(=> @_aes.encrypt(super(value))).orNull()
  _deprocessValue: (raw_value) -> Try(=> super(@_aes.decrypt(raw_value))).orNull()

# Secure version of the ledger.storage.ChromeStore. This store uses AES encryption for storing keys and data
class @ledger.storage.SecureStore extends ledger.storage.ChromeStore

  # @param [String] name The store name
  # @param [String] key The secure key used to encrypt and decrypt data with AES
  constructor: (name, key) ->
    super(name)
    @_aes = new ledger.crypto.AES(key)
    @_hasCalledKeys = no
    @_keysCache = []

  # @see Store.keys
  keys: (cb) ->
    if @_hasCalledKeys
      _.defer => cb?(@_keysCache)
    else
      super (encrypted_keys) =>
        @_keysCache = _.uniq(@_keysCache.concat(_.compact(Try(=> @_aes.decrypt(encrypted_key)).orNull() for encrypted_key in encrypted_keys)))
        @_hasCalledKeys = yes
        cb?(@_keysCache)

  _preprocessKey: (key) ->
    @_keysCache.push key unless _(@_keysCache).contains(key)
    super(@_aes.encrypt(key))

  _deprocessKey: (raw_key) ->
    key = Try(=> @_aes.decrypt(super(raw_key))).orNull()
    @_keysCache.push key unless _(@_keysCache).contains(key)
    key

  _preprocessValue: (value) -> Try(=> @_aes.encrypt(super(value))).orNull()
  _deprocessValue: (raw_value) -> Try(=> super(@_aes.decrypt(raw_value))).orNull()

Fix secure store get keys

Fix secure store get keys


class Link
  constructor: (@page, @$link) ->

  allows_process: (event) ->
    !(this._cross_origin_link(event.currentTarget) ||
      this._non_standard_click(event))

  process: ->
    type = if (@$link.data('push') == 'partial')
      'partial'
    else
      'template'

    @page.load(@$link.attr("href"), @$link.data('target'), type)

  # We split host because IE returns host with port and other browsers not
  #
  _cross_origin_link: (link) ->
    (location.protocol != link.protocol) ||
    (location.host.split(':')[0] != link.host.split(':')[0])

  _non_standard_click: (event) ->
    event.metaKey || event.ctrlKey || event.shiftKey || event.altKey

window._Wiselinks = {} if window._Wiselinks == undefined
window._Wiselinks.Link = Link

class Link
  constructor: (@page, @$link) ->

  allows_process: (event) ->
    !(this._cross_origin_link(event.currentTarget) ||
      this._non_standard_click(event))

  process: ->
    type = if (@$link.data('push') == 'partial')
      'partial'
    else
      'template'

    @page.load(@$link.attr("href"), @$link.data('target'), type)

  # We split host because IE returns host with port and other browsers not
  #
  _cross_origin_link: (link) ->
    (location.protocol != link.protocol) ||
    (location.port != link.port) ||
    (location.host.split(':')[0] != link.host.split(':')[0])

  _non_standard_click: (event) ->
    event.metaKey || event.ctrlKey || event.shiftKey || event.altKey

window._Wiselinks = {} if window._Wiselinks == undefined
window._Wiselinks.Link = Link

Check for port change during link processing


Meteor.startup ->
	Migrations.add
		version: 7
		up: ->

			console.log 'Populate urls in messages'
			query = ChatMessage.find({ 'urls.0': { $exists: true }, urls: { $type: 2 } })
			count = query.count()
			query.forEach (message, index) ->
				console.log "#{index + 1} / #{count}"

				message.urls = message.urls.map (url) ->
					if _.isString url
						return {url: url}
					return url

				OEmbed.RocketUrlParser message

			console.log 'End'

Meteor.startup ->
	Migrations.add
		version: 7
		up: ->

			console.log 'Populate urls in messages'
			query = ChatMessage.find({ 'urls.0': { $exists: true } })
			count = query.count()
			query.forEach (message, index) ->
				console.log "#{index + 1} / #{count}"

				message.urls = message.urls.map (url) ->
					if _.isString url
						return {url: url}
					return url

				OEmbed.RocketUrlParser message

			console.log 'End'

Update migration 7 to interate over all messages with urls


'atom-workspace':
  'cmd-shift-c': 'git:toggle-git-panel'

'.git-StagingView':
  'left': 'git:focus-diff-view'

'.git-CommitView-editor atom-text-editor:not([mini])':
  'cmd-enter': 'git:commit'
  'ctrl-enter': 'git:commit'

'.git-FilePatchView':
  '/': 'git:toggle-patch-selection-mode'
  'tab': 'git:select-next-hunk'
  'shift-tab': 'git:select-previous-hunk'
  'right': 'git:focus-git-panel'

'.git-Prompt-input':
  'enter': 'core:confirm'
  'esc': 'core:cancel'

'.platform-darwin':
  'cmd-shift-c': 'git:toggle-git-panel'

'.platform-win32, .platform-linux':
  'alt-shift-c': 'git:toggle-git-panel'

'.git-StagingView':
  'left': 'git:focus-diff-view'

'.git-CommitView-editor atom-text-editor:not([mini])':
  'cmd-enter': 'git:commit'
  'ctrl-enter': 'git:commit'

'.git-FilePatchView':
  '/': 'git:toggle-patch-selection-mode'
  'tab': 'git:select-next-hunk'
  'shift-tab': 'git:select-previous-hunk'
  'right': 'git:focus-git-panel'

'.git-Prompt-input':
  'enter': 'core:confirm'
  'esc': 'core:cancel'

Add menu and Win32/Linux keybindings

Add menu and Win32/Linux keybindings


{Tool} = require './base'
{createShape} = require '../core/shapes'

module.exports = class Pan extends Tool

  name: 'Pan'
  iconName: 'pan'
  usesSimpleAPI: false

  didBecomeActive: (lc) ->
    unsubscribeFuncs = []
    @unsubscribe = =>
      for func in unsubscribeFuncs
        func()

    unsubscribeFuncs.push lc.on 'lc-pointerdown', ({rawX, rawY}) =>
      @oldPosition = lc.position
      @pointerStart = {x: rawX, y: rawY}

    unsubscribeFuncs.push lc.on 'lc-pointerdrag', ({rawX, rawY}) =>
      dp = {
        x: (rawX - @pointerStart.x),
        y: (rawY - @pointerStart.y)
      }
      lc.setPan(@oldPosition.x + dp.x, @oldPosition.y + dp.y)

  willBecomeInactive: (lc) ->
    @unsubscribe()

{Tool} = require './base'
{createShape} = require '../core/shapes'

module.exports = class Pan extends Tool

  name: 'Pan'
  iconName: 'pan'
  usesSimpleAPI: false

  didBecomeActive: (lc) ->
    unsubscribeFuncs = []
    @unsubscribe = =>
      for func in unsubscribeFuncs
        func()

    unsubscribeFuncs.push lc.on 'lc-pointerdown', ({rawX, rawY}) =>
      @oldPosition = lc.position
      @pointerStart = {x: rawX, y: rawY}

    unsubscribeFuncs.push lc.on 'lc-pointerdrag', ({rawX, rawY}) =>
      # okay, so this is really bad:
      # lc.position is "buggy screen coordinates": correct on non-retina,
      # probably wrong on retina. compensate here; in v0.5 we should put the
      # offset in drawing coordinates.
      dp = {
        x: (rawX - @pointerStart.x) * lc.backingScale,
        y: (rawY - @pointerStart.y) * lc.backingScale
      }
      lc.setPan(@oldPosition.x + dp.x, @oldPosition.y + dp.y)

  willBecomeInactive: (lc) ->
    @unsubscribe()

Fix pan tool on retina

Fix pan tool on retina


# Description:
#   To create something that's… that's genuinely new,
#   you have to… to start again.
#
# Dependencies:
#   None
#
# Configuration:
#   None
#
# Commands:
#   <anything Ivey> - Display an Ive
#
# Author:
#   arbales

ives = [
  "http://www.blogcdn.com/www.engadget.com/media/2012/03/jony-ive-10-20-09.jpg",
  "http://betanews.com/wp-content/uploads/media/60/6057.png",
  "http://www.socialgazelle.com/wp-content/uploads/2012/05/jonathan-ive.jpg",
  "http://www3.pcmag.com/media/images/238530-jonathan-ive.jpg",
  "http://farm5.static.flickr.com/4089/5213864251_6a686844ca.jpg",
  "http://www.ipadforums.net/wallpapers/data/500/jonathan_ive.JPG",
  "http://www.wearesuperfamous.com/wp-content/jonny_ive11.jpg"
]

module.exports = (robot) ->
  robot.hear /.*(essential|elegant|efficient|experience|incredible|meticulous|unibody|from the ground up).*/i, (msg) ->
    msg.send msg.random ives

# Description:
#   To create something that's… that's genuinely new,
#   you have to… to start again.
#
# Dependencies:
#   None
#
# Configuration:
#   None
#
# Commands:
#   <anything Ivey> - Display an Ive
#
# Author:
#   arbales

ives = [
  "http://www.blogcdn.com/www.engadget.com/media/2012/03/jony-ive-10-20-09.jpg",
  "http://betanews.com/wp-content/uploads/media/60/6057.png",
  "http://www.socialgazelle.com/wp-content/uploads/2012/05/jonathan-ive.jpg",
  "http://www3.pcmag.com/media/images/238530-jonathan-ive.jpg",
  "http://farm5.static.flickr.com/4089/5213864251_6a686844ca.jpg",
  "http://www.ipadforums.net/wallpapers/data/500/jonathan_ive.JPG",
  "http://www.wearesuperfamous.com/wp-content/jonny_ive11.jpg"
]

module.exports = (robot) ->
  robot.hear /(essential|elegant|efficient|experience|incredible|meticulous|unibody|from the ground up)/i, (msg) ->
    msg.send msg.random ives

Remove superflous additions to Jony's regex per @tombell.


Page  = require 'controllers/page'
Api = require 'zooniverse/lib/api'

class HomePage extends Page
  el: $('.home')
  className: 'home'
  template: require 'views/home'

  elements:
    '.participants': 'participants'
    '.images': 'images'

  constructor: ->
    super
    @html @template

    Api.current.get '/projects/spacewarp', (project) =>
      @participants.html @formatNumber project.user_count
      @images.html @formatNumber project.classification_count

  formatNumber: (n) ->
    n.toString().replace /(\d)(?=(\d{3})+(?!\d))/g, '$1,'

module.exports = HomePage

Page  = require 'controllers/page'
Api = require 'zooniverse/lib/api'

FILMING = true

class HomePage extends Page
  el: $('.home')
  className: 'home'
  template: require 'views/home'

  elements:
    '.participants': 'participants'
    '.images': 'images'

  constructor: ->
    super
    @html @template

    Api.current.get '/projects/spacewarp', (project) =>
      if FILMING
        @participants.html 0
        @images.html @formatNumber 0
      else
        @participants.html @formatNumber project.user_count
        @images.html @formatNumber project.classification_count

  formatNumber: (n) ->
    n.toString().replace /(\d)(?=(\d{3})+(?!\d))/g, '$1,'

module.exports = HomePage

Set metrics to zero for now

Set metrics to zero for now


Import = require '../lib/import'
CONS = require '../lib/constants'
fs = require 'fs'
argv = require('optimist')
  .usage('Usage: $0 --projectKey key --clientId id --clientSecret secret --csv file --language lang --publish')
  .default('lang', 'en')
  .describe('projectKey', 'your SPHERE.IO project-key')
  .describe('clientId', 'your OAuth client id for the SPHERE.IO API')
  .describe('clientSecret', 'your OAuth client secret for the SPHERE.IO API')
  .describe('csv', 'CSV file containing products to import')
  .describe('language', 'Default language to using during import')
  .describe('publish', 'When given, all changes will be published immediately')
  .demand(['projectKey', 'clientId', 'clientSecret', 'csv'])
  .argv

timeout = argv.timeout
timeout or= 60000

CONS.DEFAULT_LANGUAGE = argv.language

options =
  config:
    project_key: argv.projectKey
    client_id: argv.clientId
    client_secret: argv.clientSecret
  timeout: timeout
  show_progress: true

importer = new Import options
importer.publishProducts = argv.publish

fs.readFile argv.csv, 'utf8', (err, content) ->
  if err
    console.error "Problems on reading file '#{argv.csv}': " + err
    process.exit 2

  importer.import content, (result) ->
    console.log result.message
    process.exit 0 if result.status is true
    process.exit 1

Import = require '../lib/import'
package_json = require '../package.json'
CONS = require '../lib/constants'
fs = require 'fs'
argv = require('optimist')
  .usage('Usage: $0 --projectKey key --clientId id --clientSecret secret --csv file --language lang --publish')
  .default('lang', 'en')
  .describe('projectKey', 'your SPHERE.IO project-key')
  .describe('clientId', 'your OAuth client id for the SPHERE.IO API')
  .describe('clientSecret', 'your OAuth client secret for the SPHERE.IO API')
  .describe('csv', 'CSV file containing products to import')
  .describe('language', 'Default language to using during import')
  .describe('publish', 'When given, all changes will be published immediately')
  .demand(['projectKey', 'clientId', 'clientSecret', 'csv'])
  .argv

timeout = argv.timeout
timeout or= 60000

CONS.DEFAULT_LANGUAGE = argv.language

options =
  config:
    project_key: argv.projectKey
    client_id: argv.clientId
    client_secret: argv.clientSecret
  timeout: timeout
  show_progress: true
  user_agent: "#{package_json.name} - #{package_json.version}"

importer = new Import options
importer.publishProducts = argv.publish

fs.readFile argv.csv, 'utf8', (err, content) ->
  if err
    console.error "Problems on reading file '#{argv.csv}': " + err
    process.exit 2

  importer.import content, (result) ->
    console.log result.message
    process.exit 0 if result.status is true
    process.exit 1

Send name and version as user agent.

Send name and version as user agent.


FS = require 'fs'
Q = require 'q'

###
Class for generating JSON product type representations from CSV files.
###
class ProductTypeGenerator

  _options = {}

  constructor: (options = {}) ->
    @_options = options

  ###
  Creates sphere product type representation files using JSON format.
  @param {array} types Entire types CSV as an array of records.
  @param {array} attributes Entire attributes CSV as an array of records.
  @param {function} callback The callback function to be invoked when the method finished its work.
  @return Result of the given callback
  ###
  run: (types, attributes, callback) ->
    callback true

module.exports = ProductTypeGenerator

FS = require 'fs'
Q = require 'q'

###
Class for generating JSON product type representations from CSV files.
###
class ProductTypeGenerator

  constructor: (options = {}) ->
    @_options = options

  ###
  Creates sphere product type representation files using JSON format.
  @param {array} types Entire types CSV as an array of records.
  @param {array} attributes Entire attributes CSV as an array of records.
  @param {function} callback The callback function to be invoked when the method finished its work.
  @return Result of the given callback
  ###
  run: (types, attributes, callback) ->
    callback true

module.exports = ProductTypeGenerator

Remove explicit variable declaration as its done by cs anyhow.


MinimapSelectionView = require './minimap-selection-view'

module.exports =

  active: false
  views: {}

  activate: (state) ->
    try
      atom.packages.activatePackage('minimap').then (minimapPackage) =>
        @minimap = minimapPackage.mainModule
        return @deactivate() unless @minimap.versionMatch('>= 3.5.0')

        @minimap.registerPlugin 'selection', this
    catch
      @deactivate

  deactivate: ->
    @minimap.unregisterPlugin 'selection'
    @minimap = null

  isActive: -> @active

  activatePlugin: ->
    return if @active
    @active = true

    @subscription = @minimap.observeMinimaps (o) =>
      minimap = o.view ? o
      selectionView = new MinimapSelectionView(minimap)

      @views[minimap.getTextEditor().id] = selectionView

  deactivatePlugin: ->
    return unless @active
    view.destroy() for id,view of @views
    @active = false
    @views = {}

    @subscription.off()

MinimapSelectionView = require './minimap-selection-view'

module.exports =

  active: false
  views: {}

  activate: (state) ->
    try
      atom.packages.activatePackage('minimap').then (minimapPackage) =>
        @minimap = minimapPackage.mainModule
        return @deactivate() unless @minimap.versionMatch('>= 3.5.0')

        @minimap.registerPlugin 'selection', this
    catch
      @deactivate

  deactivate: ->
    @minimap.unregisterPlugin 'selection'
    @minimap = null

  isActive: -> @active

  activatePlugin: ->
    return if @active
    @active = true

    @subscription = @minimap.observeMinimaps (o) =>
      minimap = o.view ? o
      selectionView = new MinimapSelectionView(minimap)

      @views[minimap.getTextEditor().id] = selectionView

  deactivatePlugin: ->
    return unless @active
    view.destroy() for id,view of @views
    @active = false
    @views = {}

    @subscription.dispose()

Remove call to deprecated method

:bug: Remove call to deprecated method


data =
  metrics:
    anon:
      colour: 'orange', number: 'loading...', title: 'Anonymous Visitors'
    ,
    normal:
      colour: 'blue', number: 'loading...', title: 'Normal Visitors'
    ,
    premium:
      colour: 'green', number: 'loading...', title: 'Premium Visitors'

source = $('#metric-block-template').html()
template = Handlebars.compile source
$('.metric-channel-blocks').html template(data)

socket = io.connect "http://#{window.location.hostname}"
socket.emit 'ready'
socket.on 'metric', (payload) ->
  for key of payload.metrics
    data.metrics[key].number = payload.metrics[key]

  $('.metric-channel-blocks').html template(data)

data =
  metrics:
    anon:
      colour: 'orange', number: '...', title: 'Anonymous Visitors'
    ,
    normal:
      colour: 'blue', number: '...', title: 'Logged-in Visitors'
    ,
    premium:
      colour: 'green', number: '...', title: 'Premium Visitors'

source = $('#metric-block-template').html()
template = Handlebars.compile source
$('.metric-channel-blocks').html template(data)

socket = io.connect "http://#{window.location.hostname}"
socket.emit 'ready'
socket.on 'metric', (payload) ->
  for key of payload.metrics
    data.metrics[key].number = payload.metrics[key]

  $('.metric-channel-blocks').html template(data)

Rename normal users to logged-in users, loading now ...


Add comment heading to document ready

Add comment heading to document ready


React = require 'react'
BS = require 'react-bootstrap'

MESSAGES = {
  student: [

Tutor shows your weakest topics so you can practice to improve.

Try to get all of your topics to green!

  ]
  teacher: [

Tutor shows the weakest topics for each period.

Students may need your help in those areas.

  ]
  teacher_student: [

Tutor shows the weakest topics for the student.

They may need your help in those areas.

  ]
}

module.exports = React.createClass

  displayName: 'LearningGuideInfoLink'
  type: React.PropTypes.oneOf(['student', 'teacher', 'teacher_student']).isRequired

  render: ->
    tooltip =
    <BS.Tooltip className='info-link-tooltip' html='true'>

The performance forecast is an estimate of your understanding of a topic.

It is personalized display based on your answers to reading questions,
      homework problems, and previous practices.

      {MESSAGES[@props.type]}
    </BS.Tooltip>

    <BS.OverlayTrigger placement='right' overlay={tooltip}>

    </BS.OverlayTrigger>

React = require 'react'
BS = require 'react-bootstrap'

MESSAGES = {
  student: [

The performance forecast is an estimate of your understanding of a topic.

        It is personalized display based on your answers to reading questions,
        homework problems, and previous practices.

  ]
  teacher: [

The performance forecast is an estimate of each period's understanding of a topic.

        It is personalized display based on their answers to reading questions,
        homework problems, and previous practices.

  ]
  teacher_student: [

The performance forecast is an estimate of each student's understanding of a topic.

        It is personalized display based on their answers to reading questions,
        homework problems, and previous practices.

  ]
}

module.exports = React.createClass

  displayName: 'LearningGuideInfoLink'
  type: React.PropTypes.oneOf(['student', 'teacher', 'teacher_student']).isRequired

  render: ->
    tooltip =
    <BS.Tooltip className='info-link-tooltip' html='true'>
      {MESSAGES[@props.type]}
    </BS.Tooltip>

    <BS.OverlayTrigger placement='right' overlay={tooltip}>

    </BS.OverlayTrigger>

Set messages to correct phrases

Set messages to correct phrases


Trix.galleryFilter = (snapshot) ->
  filter = new Filter snapshot
  filter.perform()
  filter.getSnapshot()

class Filter
  constructor: (snapshot) ->
    {@document, @selectedRange} = snapshot

  perform: ->
    @removeGalleryAttribute()
    @applyGalleryAttribute()

  getSnapshot: ->
    {@document, @selectedRange}

  # Private

  removeGalleryAttribute: ->
    for range in @findRangesOfGalleryBlocks()
      @document = @document.removeAttributeAtRange("gallery", range)

  applyGalleryAttribute: ->
    offset = 0
    for range in @findRangesOfGalleryPieces() when range[1] - range[0] > 1
      range[0] += offset
      range[1] += offset

      unless @document.getCharacterAtPosition(range[1]) is "\n"
        @document = @document.insertBlockBreakAtRange(range[1])
        offset++

      unless range[0] is 0
        unless @document.getCharacterAtPosition(range[0] - 1) is "\n"
          @document = @document.insertBlockBreakAtRange(range[0])
          offset++

      @document = @document.applyBlockAttributeAtRange("gallery", true, range)

  findRangesOfGalleryBlocks: ->
    @document.findRangesForBlockAttribute("gallery")

  findRangesOfGalleryPieces: ->
    @document.findRangesForTextAttribute("presentation", withValue: "gallery")

Trix.galleryFilter = (snapshot) ->
  filter = new Filter snapshot
  filter.perform()
  filter.getSnapshot()

class Filter
  constructor: (snapshot) ->
    {@document, @selectedRange} = snapshot

  perform: ->
    @removeGalleryAttribute()
    @applyGalleryAttribute()

  getSnapshot: ->
    {@document, @selectedRange}

  # Private

  removeGalleryAttribute: ->
    for range in @findRangesOfGalleryBlocks()
      @document = @document.removeAttributeAtRange("gallery", range)

  applyGalleryAttribute: ->
    offset = 0
    for range in @findRangesOfGalleryPieces() when range[1] - range[0] > 1
      range[0] += offset
      range[1] += offset

      unless @document.getCharacterAtPosition(range[1]) is "\n"
        @document = @document.insertBlockBreakAtRange(range[1])
        @moveSelectedRangeForward() if range[1] < @selectedRange[1]
        offset++

      unless range[0] is 0
        unless @document.getCharacterAtPosition(range[0] - 1) is "\n"
          @document = @document.insertBlockBreakAtRange(range[0])
          @moveSelectedRangeForward() if range[0] < @selectedRange[0]
          offset++

      @document = @document.applyBlockAttributeAtRange("gallery", true, range)

  findRangesOfGalleryBlocks: ->
    @document.findRangesForBlockAttribute("gallery")

  findRangesOfGalleryPieces: ->
    @document.findRangesForTextAttribute("presentation", withValue: "gallery")

  moveSelectedRangeForward: ->
    @selectedRange[0] += 1
    @selectedRange[1] += 1

Adjust selection when inserting gallery block breaks


#= require ./abstract_binding

class Batman.DOM.RouteBinding extends Batman.DOM.AbstractBinding
  onAnchorTag: false
  onlyObserve: Batman.BindingDefinitionOnlyObserve.Data

  @accessor 'dispatcher', ->
    @view.lookupKeypath('dispatcher') || Batman.App.get('current.dispatcher')

  bind: ->
    if (@node.nodeName is 'A' || @node.nodeName is 'a')
      @onAnchorTag = true

    super

    return if @onAnchorTag && @node.getAttribute('target')
    Batman.DOM.events.click(@node, @routeClick)

  routeClick: (node, event) =>
    return if event.__batmanActionTaken
    event.__batmanActionTaken = true
    params = @pathFromValue(@get('filteredValue'))
    Batman.redirect(params) if params?

  dataChange: (value) ->
    if value
      path = @pathFromValue(value)

    if @onAnchorTag
      if path and Batman.navigator
        path = Batman.navigator.linkTo(path)
      else
        path = "#"

      @node.href = path

  pathFromValue: (value) ->
    if value
      if value.isNamedRouteQuery
        value.get('path')
      else
        @get('dispatcher')?.pathFromParams(value)

#= require ./abstract_binding

class Batman.DOM.RouteBinding extends Batman.DOM.AbstractBinding
  onAnchorTag: false
  onlyObserve: Batman.BindingDefinitionOnlyObserve.Data

  @accessor 'dispatcher', ->
    @view.lookupKeypath('dispatcher') || Batman.App.get('current.dispatcher')

  bind: ->
    if @node.nodeName in ['a','A']
      @onAnchorTag = true

    super

    return if @onAnchorTag && @node.getAttribute('target')
    Batman.DOM.events.click(@node, @routeClick)

  routeClick: (node, event) =>
    return if event.__batmanActionTaken
    event.__batmanActionTaken = true
    params = @pathFromValue(@get('filteredValue'))
    Batman.redirect(params) if params?

  dataChange: (value) ->
    if value
      path = @pathFromValue(value)

    if @onAnchorTag
      if path and Batman.navigator
        path = Batman.navigator.linkTo(path)
      else
        path = "#"

      @node.href = path

  pathFromValue: (value) ->
    if value
      if value.isNamedRouteQuery
        value.get('path')
      else
        @get('dispatcher')?.pathFromParams(value)

Switch to using in so coffeescript can optimize


class @Overlay
  constructor: (contentSelector, options) ->
    @contentSelector = contentSelector
    @options = options || {}
    defaults =
      domType: OverlayDomWrapper
      dimensionsType: OverlayDimensions
    @options = $.extend(defaults, @options)
    @dom = new @options.domType()
    $('body').append(@dom.el).append(@dom.mask)

    @createDimensions = ->
      new @options.dimensionsType(@originalContent)

  open: (target) ->
    @prepareOpen(target)
    @setDimensions()
    @show()

  prepareOpen: (target = document) ->
    @dom.mask.show()
    @lockScroll()
    @originalContent = $(target).find(@contentSelector)
    @overlayContent = @originalContent.clone()
    @dom.el.append(@overlayContent)
    @dimensions = @createDimensions()

  setDimensions: ->
    @dom.el.css('left', @dimensions.margin())
    @dom.el.css('top', @dimensions.top())
    @dom.el.width(@dimensions.width())
    @dom.closeButton().css('left', @dimensions.closeButtonLeftPosition())

  show: ->
    @overlayContent.show()
    @dom.el.show()
    @overlayContent.trigger('overlay:show')

  setMaskHeight: ->
    @dom.mask.height($(document).height())

  lockScroll: ->
    $('body').addClass('scroll-lock') unless window.mobileLayout()

  close: ->
    @dom.el.empty().hide()
    @dom.mask.hide()
    $('body').removeClass('scroll-lock')

class @Overlay
  constructor: (contentSelector, options) ->
    @contentSelector = contentSelector
    @options = options || {}
    defaults =
      domType: OverlayDomWrapper
      dimensionsType: OverlayDimensions
    @options = $.extend(defaults, @options)
    @dom = new @options.domType()
    $('body').append(@dom.el).append(@dom.mask)

    @createDimensions = ->
      new @options.dimensionsType(@originalContent)

  open: (target) ->
    @prepareOpen(target)
    @setDimensions()
    @show()

  prepareOpen: (target = document) ->
    @dom.mask.show()
    @lockScroll()
    @originalContent = $(target).find(@contentSelector)
    @overlayContent = @originalContent.clone()
    @dom.el.append(@overlayContent)
    @dimensions = @createDimensions()

  setDimensions: ->
    @dom.el.css('left', @dimensions.margin())
    @dom.el.css('top', @dimensions.top())
    @dom.el.width(@dimensions.width())
    @dom.mask.height('100%')
    @dom.closeButton().css('left', @dimensions.closeButtonLeftPosition())

  show: ->
    @overlayContent.show()
    @dom.el.show()
    @overlayContent.trigger('overlay:show')

  setMaskHeight: ->
    @dom.mask.height($(document).height())

  lockScroll: ->
    $('body').addClass('scroll-lock') unless window.mobileLayout()

  close: ->
    @dom.el.empty().hide()
    @dom.mask.hide()
    $('body').removeClass('scroll-lock')

Reset mask height on close

Reset mask height on close

Otherwise it will never shrink after opening long content


#= require env
#= require jquery
#= require jquery/jquery-migrate
#= require jquery/jquery.cookies.js
#= require i18n.js
#= require bootstrap
#= require bootstrap-select
#= require custom-bootstrap.js.coffee
#= require function
#= require map-overlay.js
#= require handlebars
#= require ember
#= require ember-data
#= require spin
#= require leaflet/leaflet-src
#= require leaflet/leaflet.locate
#= require ember-leaflet
#= require jquery/jquery.magnific-popup.js
#= require responsive-popover
#= require dropzone
#= require_self
#= require wheelmap

I18n.defaultLocale = 'de'
I18n.locale = $('html').attr('lang')
I18n.fallbacks = true

Ember.Application.reopen
  # Transition end event
  customEvents: (()->
    customEvents = {}

    if $.support.transition?
      customEvents[$.support.transition.end] = 'transitionEnd'

    customEvents
  ).property()

Wheelmap = @Wheelmap = Ember.Application.create
  # LOG_TRANSITIONS: true
  rootElement: '#wheelmap'

DS.RESTAdapter.reopen
  buildURL: (type, id)->
    # Needed for not having wrong cached urls
    @_super(type, id) + '.json'

Wheelmap.Router.reopen
  rootURL: '/map/'

#= require env
#= require jquery
#= require jquery/jquery-migrate
#= require jquery/jquery.cookies.js
#= require i18n.js
#= require bootstrap
#= require bootstrap-select
#= require custom-bootstrap.js.coffee
#= require function
#= require map-overlay.js
#= require handlebars
#= require ember
#= require ember-data
#= require spin
#= require leaflet/leaflet-src
#= require leaflet/leaflet.locate
#= require ember-leaflet
#= require jquery/jquery.magnific-popup.js
#= require responsive-popover
#= require dropzone
#= require_self
#= require wheelmap

I18n.defaultLocale = 'en'
I18n.locale = $('html').attr('lang')
I18n.fallbacks = true

Ember.Application.reopen
  # Transition end event
  customEvents: (()->
    customEvents = {}

    if $.support.transition?
      customEvents[$.support.transition.end] = 'transitionEnd'

    customEvents
  ).property()

Wheelmap = @Wheelmap = Ember.Application.create
  # LOG_TRANSITIONS: true
  rootElement: '#wheelmap'

DS.RESTAdapter.reopen
  buildURL: (type, id)->
    # Needed for not having wrong cached urls
    @_super(type, id) + '.json'

Wheelmap.Router.reopen
  rootURL: '/map/'

Change default local for JS I18n.

Change default local for JS I18n.


express = require('express')

module.exports = ->
  router = express.Router()
  router.get '/framestream', (req, res) ->
    req.socket.setTimeout Infinity

    messageCount = 1
    subscriberCount = 0

    subscriber = require('./redis_client')()

    subscriber.subscribe 'updates'

    subscriber.on 'error', (err) ->
      console.error('Redis Error: ' + err)

    subscriber.on 'subscribe', (err) ->
      subscriberCount++

    subscriber.on "message", (channel, message) ->
      messageCount++
      res.write 'id: ' + messageCount + '\n'
      res.write 'data: ' + message + '\n\n'

    res.writeHead 200,
      'Content-Type': 'text/event-stream'
      'Cache-Control': 'no-cache'
      'Connection': 'keep-alive'

    res.write '\n'

    req.on 'close', ->
      subscriberCount--
      subscriber.unsubscribe()
      subscriber.quit()
  router

express = require('express')

module.exports = ->
  router = express.Router()
  router.get '/framestream', (req, res) ->
    req.socket.setTimeout 1000*1000

    messageCount = 1
    subscriberCount = 0

    subscriber = require('./redis_client')()

    subscriber.subscribe 'updates'

    subscriber.on 'error', (err) ->
      console.error('Redis Error: ' + err)

    subscriber.on 'subscribe', (err) ->
      subscriberCount++

    subscriber.on "message", (channel, message) ->
      messageCount++
      res.write 'id: ' + messageCount + '\n'
      res.write 'data: ' + message + '\n\n'

    res.writeHead 200,
      'Content-Type': 'text/event-stream'
      'Cache-Control': 'no-cache'
      'Connection': 'keep-alive'

    res.write '\n'

    req.on 'close', ->
      subscriberCount--
      subscriber.unsubscribe()
      subscriber.quit()
  router

Set finite timeout for framestream

Set finite timeout for framestream


{View} = require 'space-pen'
$ = require 'jquery'
_ = require 'underscore'

module.exports =
class WrapGuideView extends View
  @activate: ->
    rootView.eachEditor (editor) =>
      @appendToEditorPane(rootView, editor) if editor.attached

  @appendToEditorPane: (rootView, editor) ->
    if underlayer = editor.find('.underlayer')
      underlayer.append(new WrapGuideView(editor))

  @content: ->
    @div class: 'wrap-guide'

  defaultColumn: 80

  initialize: (@editor) =>
    @observeConfig 'editor.fontSize', => @updateGuide()
    @subscribe @editor, 'editor:path-changed', => @updateGuide()
    @subscribe @editor, 'editor:min-width-changed', => @updateGuide()
    @subscribe $(window), 'resize', => @updateGuide()

  getGuideColumn: (path) ->
    customColumns = config.get('wrapGuide.columns')
    return @defaultColumn unless _.isArray(customColumns)
    for customColumn in customColumns
      continue unless _.isObject(customColumn)
      pattern = customColumn['pattern']
      continue unless pattern
      return parseInt(customColumn['column']) if new RegExp(pattern).test(path)
    @defaultColumn

  updateGuide: ->
    column = @getGuideColumn(@editor.getPath(), @defaultColumn)
    if column > 0
      columnWidth = @editor.charWidth * column
      if columnWidth < @editor.layerMinWidth or columnWidth < @editor.width()
        @css('left', "#{columnWidth}px").show()
      else
        @hide()
    else
      @hide()

{View} = require 'space-pen'
$ = require 'jquery'
_ = require 'underscore'

module.exports =
class WrapGuideView extends View
  @activate: ->
    rootView.eachEditor (editor) =>
      @appendToEditorPane(rootView, editor) if editor.attached

  @appendToEditorPane: (rootView, editor) ->
    if underlayer = editor.find('.underlayer')
      underlayer.append(new WrapGuideView(editor))

  @content: ->
    @div class: 'wrap-guide'

  defaultColumn: 80

  initialize: (@editor) =>
    @observeConfig 'editor.fontSize', => @updateGuide()
    @subscribe @editor, 'editor:path-changed', => @updateGuide()
    @subscribe @editor, 'editor:min-width-changed', => @updateGuide()
    @subscribe $(window), 'resize', => @updateGuide()

  getGuideColumn: (path) ->
    customColumns = config.get('wrapGuide.columns')
    return @defaultColumn unless _.isArray(customColumns)
    for customColumn in customColumns
      continue unless _.isObject(customColumn)
      pattern = customColumn['pattern']
      continue unless pattern
      return parseInt(customColumn['column']) if new RegExp(pattern).test(path)
    @defaultColumn

  updateGuide: ->
    column = @getGuideColumn(@editor.getPath(), @defaultColumn)
    if column > 0
      columnWidth = @editor.charWidth * column
      if columnWidth < @editor.layerMinWidth or columnWidth < @editor.width()
        @css('left', columnWidth).show()
      else
        @hide()
    else
      @hide()

Set left as number without px suffix

Set left as number without px suffix


'context-menu':
  '.tree-view':
    'Add file': 'tree-view:add'

'context-menu':
  '.tree-view':
    'Add File': 'tree-view:add'
    'Rename': 'tree-view:move'
    'Delete': 'tree-view:remove'

Add rename and delete menu items

Add rename and delete menu items


Neighborly.Users ?= {}

Neighborly.Users.Payments =
  modules: -> []
  init: Backbone.View.extend
    el: '.user-payments-content'

    initialize: ->
      $accounts = $(".account-method")

      for account in $accounts
        $account = $(account)
        if $account.data('path')
          $.get($account.data('path')).success (data) =>
            $account.html data
            Initjs.initializePartial()

            $('.use-existing-item input:not(#payment_show_bank_existing)')
              .attr('disabled', '1')

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


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

  describe "PropertyContainerView", ->
    it "recognizes non-quoted strings as strings", ->
      pcv = new PropertyContainerView(template:null)

      expect(pcv.shouldBeConvertedToString "a").toBe(true)
      expect(pcv.shouldBeConvertedToString "åäö").toBe(true)
      expect(pcv.shouldBeConvertedToString "åäö #$ asd  ").toBe(true)
      expect(pcv.shouldBeConvertedToString ";åäö #$ asd  ").toBe(true)

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

      expect(pcv.shouldBeConvertedToString "['1','2','3']").toBe(false)
      expect(pcv.shouldBeConvertedToString "[1,2,3]").toBe(false)

      expect(pcv.shouldBeConvertedToString '"a quoted string"').toBe(false)

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

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

      expect(pcv.shouldBeConvertedToString "a").toBe(true)
      expect(pcv.shouldBeConvertedToString "abcd123 ").toBe(true)

    it "recognizes odd characters as strings", ->
      pcv = new PropertyContainerView(template:null)

      expect(pcv.shouldBeConvertedToString "åäö").toBe(true)
      expect(pcv.shouldBeConvertedToString "åäö #$ asd  ").toBe(true)
      expect(pcv.shouldBeConvertedToString ";åäö #$ asd  ").toBe(true)

    it "recognizes valid JSON values as not being strings", ->
      pcv = new PropertyContainerView(template:null)

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

      expect(pcv.shouldBeConvertedToString "['1','2','3']").toBe(false)
      expect(pcv.shouldBeConvertedToString "[1,2,3]").toBe(false)

      expect(pcv.shouldBeConvertedToString '"a quoted string"').toBe(false)

Split webadmin string recognizer into multiple tests.


'.platform-darwin':
  'ctrl-g': 'go-to-line:toggle'

'.platform-win32':
  'ctrl-g': 'go-to-line:toggle'

'.platform-linux':
  'ctrl-i': 'go-to-line:toggle'

'.go-to-line .mini.editor input':
  'enter': 'core:confirm',
  'escape': 'core:cancel'

'.platform-darwin .go-to-line .mini.editor input':
  'cmd-w': 'core:cancel'

'.platform-win32 .go-to-line .mini.editor input':
  'ctrl-w': 'core:cancel'

'.platform-linux .go-to-line .mini.editor input':
  'ctrl-w': 'core:cancel'

'.platform-darwin, .platform-win32, .platform-linux':
  'ctrl-g': 'go-to-line:toggle'

'.go-to-line .mini.editor input':
  'enter': 'core:confirm',
  'escape': 'core:cancel'

'.platform-darwin .go-to-line .mini.editor input':
  'cmd-w': 'core:cancel'

'.platform-win32 .go-to-line .mini.editor input':
  'ctrl-w': 'core:cancel'

'.platform-linux .go-to-line .mini.editor input':
  'ctrl-w': 'core:cancel'

:penguin: Use ctrl-g for linux. Join selectors with the same keybinding.


# Keybindings require three things to be fully defined: A selector that is
# matched against the focused element, the keystroke and the command to
# execute.
#
# Below is a basic keybinding which registers on all platforms by applying to
# the root workspace element.

# For more detailed documentation see
# https://atom.io/docs/latest/advanced/keymaps

'.table-edit atom-text-editor':
  'enter': 'core:confirm'
  'ctrl-enter': 'editor:newline'
  'tab': 'table-edit:move-right'
  'shift-tab': 'table-edit:move-left'
  'ctrl-tab': 'editor:indent'

# Keybindings require three things to be fully defined: A selector that is
# matched against the focused element, the keystroke and the command to
# execute.
#
# Below is a basic keybinding which registers on all platforms by applying to
# the root workspace element.

# For more detailed documentation see
# https://atom.io/docs/latest/advanced/keymaps

'.table-edit':
  'tab': 'table-edit:move-right'
  'shift-tab': 'table-edit:move-left'

'.table-edit atom-text-editor':
  'enter': 'core:confirm'
  'ctrl-enter': 'editor:newline'
  'tab': 'table-edit:move-right'
  'shift-tab': 'table-edit:move-left'
  'ctrl-tab': 'editor:indent'

Add binding for moving left and right with tab