Update nl-NL.coffee

Update nl-NL.coffee

--- app/locale/nl-NL.coffee
+++ app/locale/nl-NL.coffee
@@ -17,7 +17,7 @@
   nav:
     play: "Levels" # The top nav bar entry where players choose which levels to play
     community: "Gemeenschap"
-#    courses: "Courses"
+    courses: "Lessen"
     editor: "Editor"
     blog: "Blog"
     forum: "Forum"
@@ -52,7 +52,7 @@

   play:
     play_as: "Speel als " # Ladder page
-#    compete: "Compete!" # Course details page
+    compete: "Compleet!" # Course details page //in English it says 'complete', so translated that instead.
     spectate: "Toeschouwen" # Ladder page
     players: "Spelers" # Hover over a level on /play
     hours_played: "Speeltijd" # Hover over a level on /play
@@ -63,7 +63,7 @@
     locked: "Vergrendeld"
     purchasable: "Te koop" # For a hero you unlocked but haven't purchased
     available: "Beschikbaar"
-#    skills_granted: "Skills Granted" # Property documentation details
+    skills_granted: "Verleende vaardigheden" # Property documentation details
     heroes: "Helden" # Tooltip on hero shop button from /play
     achievements: "Prestaties" # Tooltip on achievement list button from /play
     account: "Account" # Tooltip on account button from /play
@@ -75,7 +75,7 @@
     subscription_required: "Abonnement nodig"
     anonymous: "Anonieme Speler"
     level_difficulty: "Moeilijkheidsgraad: "
-#    play_classroom_version: "Play Classroom Version" # Choose a level in campaign version that you also can play in one of your courses
+    play_classroom_version: "Speel de klassikale versie" # Choose a level in campaign version that you also can play in one of your courses
     campaign_beginner: "Beginnercampagne"
     awaiting_levels_adventurer_prefix: "We brengen 5 nieuwe levels per week uit." # {change}
     awaiting_levels_adventurer: "Schrijf je in als Avonturier"
@@ -114,9 +114,9 @@
     log_in: "inloggen met wachtwoord"
     required: "Je moet inloggen om daarheen te gaan."
     login_switch: "Heb je al een account?"
-#    school_name: "School Name and City"
-#    optional: "optional"
-#    school_name_placeholder: "Example High School, Springfield, IL"
+    school_name: "School naam en stad"
+    optional: "optioneel"
+    school_name_placeholder: "Voorbeeld middelbare school, Amsterdam"

   recover:
     recover_account_title: "Herstel Account"
@@ -160,13 +160,13 @@
     date: "Datum"
     body: "Inhoud"
     version: "Versie"
-#    pending: "Pending"
+    pending: "In afwachting"
     accepted: "Geaccepteerd"
     rejected: "Afgewezen"
     withdrawn: "Teruggetrokken"
-#    accept: "Accept"
-#    reject: "Reject"
-#    withdraw: "Withdraw"
+    accept: "Accepteer"
+    reject: "Weiger"
+    withdraw: "Intrekken"
     submitter: "Toevoeger"
     submitted: "Toegevoegd"
     commit_msg: "Commit Bericht"
@@ -221,12 +221,12 @@
     years: "jaren"

   play_level:
-#    completed_level: "Completed Level:"
-#    course: "Course:"
+    completed_level: "Voltooid Level:"
+    course: "Les:"
     done: "Klaar"
-#    next_level: "Next Level:"
-#    next_game: "Next game"
-#    show_menu: "Show game menu"
+    next_level: "Volgende Level:"
+    next_game: "Volgende spel"
+    show_menu: "Geef spelmenu weer"
     home: "Home" # Not used any more, will be removed soon.
     level: "Level" # Like "Level: Dungeons of Kithgard"
     skip: "Overslaan"
@@ -324,25 +324,25 @@
     tip_premature_optimization: "vroegtijdig optimaliseren is de wortel van al het kwaad. - Donald Knuth"
     tip_brute_force: "Wanneer je twijfelt, gebruik brute force. - Ken Thompson"
     tip_extrapolation: "Er zijn twee soorten mensen: Zij die iets kunnen afleiden van onvolledige gegevens..."
-#    tip_superpower: "Coding is the closest thing we have to a superpower."
-#    tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
+    tip_superpower: "Van alle dingen komt programmeren het dichtst in de buurt van een superkracht."
+    tip_control_destiny: "In echte open source, hebt je het recht om je eigen toekomst te bepalen. - Linus Torvalds"
     tip_no_code: "Geen code is sneller dan geen code."
     tip_code_never_lies: "Code liegt niet, commentaar soms wel. — Ron Jeffries"
     tip_reusable_software: "voor code herbruikbaar kan zijn, moet het bruikbaar zijn."
-#    tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is ‘//’"
+    tip_optimization_operator: "Iedere taal heeft een optimalisatie operator. In de meeste talen is die operator ‘//’"
     tip_lines_of_code: "programmeervoortgang meten met lijnen code, is als vliegtuigbouwvoortgang meten bij gewicht. — Bill Gates"
     tip_source_code: "Ik wil de wereld veranderen, maar ze geven me de broncode niet."
-#    tip_javascript_java: "Java is to JavaScript what Car is to Carpet. - Chris Heilmann"
+    tip_javascript_java: "Java staat tot JavaScript, als Kar staat tot Karpet. - Chris Heilmann"
     tip_move_forward: "Wat je ook doet, ga vooruit. - Martin Luther King Jr."
     tip_google: "Heb je een probleem dat je niet kan oplossen? Googel het!"
     tip_adding_evil: "Een snufje kwaad toevoegen."
     tip_hate_computers: "Mensen die denken dat ze de computer haten, haten eigenlijk slechte programmeurs. - Larry Niven"
     tip_open_source_contribute: "Je kunt helpen CodeCombat te verbeteren!"
-#    tip_recurse: "To iterate is human, to recurse divine. - L. Peter Deutsch"
+    tip_recurse: "Itereren is menselijk, recursiveren is goddelijk. - L. Peter Deutsch"
     tip_free_your_mind: "You have to let it all go, Neo. Fear, doubt, and disbelief. Free your mind. - Morpheus"
     tip_strong_opponents: "Zelf de sterkste vijand heeft een zwakheid. - Itachi Uchiha"
     tip_paper_and_pen: "Voor je begint te programmeren, kan je altijd met pen en papier een plan maken."
-#    tip_solve_then_write: "First, solve the problem. Then, write the code. - John Johnson"
+    tip_solve_then_write: "Los eerst het probleem op. Schrijf dan de code. - John Johnson"

   game_menu:
     inventory_tab: "Inventaris"
@@ -357,20 +357,20 @@
     choose_hero_caption: "Kies held, taal"
     save_load_caption: "... en bekijk de geschiedenis"
     options_caption: "Instellingen"
-#    guide_caption: "Docs and tips"
+    guide_caption: "Documenten en tips"
     multiplayer_caption: "Speel met vrienden!"
     auth_caption: "Bewaar je voortgang."

   leaderboard:
     view_other_solutions: "Bekijk Klassement"
     scores: "Scores"
-#    top_players: "Top Players by"
+    top_players: "Top Spelers per"
     day: "Vandaag"
     week: "Deze week"
     all: "Altijd"
     time: "tijd"
-#    damage_taken: "Damage Taken"
-#    damage_dealt: "Damage Dealt"
+    damage_taken: "Schade ontvangen"
+    damage_dealt: "Schade uitgedeeld"
     difficulty: "Moeilijkheidsgraad"
     gold_collected: "Goud verzameld"

@@ -400,14 +400,14 @@
 #    price: "x3500 / mo"

   subscribe:
-#    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
+    comparison_blurb: "Verbeter je vaardigheden met een abonement op CodeCombat!"
     feature1: "meer dan 110+ basislevels over 4 werelden"
     feature2: "10 sterke nieuwe helden met unieke vaardigheden!"
     feature3: "70+ bonuslevels" # {change}
-#    feature4: "3500 bonus gems every month!"
+    feature4: "3500 bonus edelstenen elke maand!"
     feature5: "Video cursussen"
-#    feature6: "Premium email support"
-#    feature7: "Private Clans"
+    feature6: "Hoogwaardige e-mail ondersteuning"
+    feature7: "Besloten Clans"
     free: "Gratis"
     month: "maand"
     must_be_logged: "Je moet eerst ingelogd zijn. Maak een account aan of log in in het menu hierboven."
@@ -443,8 +443,8 @@
     stripe_description: "Maandelijks abonnement"
     stripe_description_year_sale: "1-jarig abonnement (${{discount}} korting)" # {change}
     subscription_required_to_play: "Je hebt een abonnement nodig om dit level te spelen."
-#    unlock_help_videos: "Subscribe to unlock all video tutorials."
-#    personal_sub: "Personal Subscription" # Accounts Subscription View below
+    unlock_help_videos: "Abonneer om toegang te krijgen tot alle instructievideos."
+    personal_sub: "Persoonlijk Abonnement" # Accounts Subscription View below
 #    loading_info: "Loading subscription information..."
 #    managed_by: "Managed by"
 #    will_be_cancelled: "Will be cancelled on"


Translation done and spell check

Translation done and spell check

--- app/locale/pt-BR.coffee
+++ app/locale/pt-BR.coffee
@@ -346,7 +346,7 @@
     nick_blurb: "Guru Motivacional"
     michael_title: "Programador"
     michael_blurb: "Administrador de Sistemas"
-    matt_title: "PProgramador"
+    matt_title: "Programador"
     matt_blurb: "O Ciclista"

   versions:
@@ -436,8 +436,8 @@
     introduction: "Verifique abaixo de que maneires você pode se envolver e decida qual lhe parece mais divertida. Esperamos trabalhar com você em breve!"
     level_editor_prefix: "Use o CodeCombat"
     level_editor_suffix: "para criar e editar níveis. Usuários criaram níveis para suas classes, amigos, hackathons, estudantes e parentes. Se criar um novo nível soa intimidador, você pode iniciar fazendo um fork de um dos nossos."
-#    thang_editor_prefix: "We call units within the game 'thangs'. Use the"
-#    thang_editor_suffix: "to modify the CodeCombat source artwork. Allow units to throw projectiles, alter the direction of an animation, change a unit's hit points, or upload your own vector sprites."
+    thang_editor_prefix: "Nós chamamos as unidades do jogo de 'thangs'. Utilize o"
+    thang_editor_suffix: "para modificar o fonte das artes. Permita que lancem projéteis, modifique a direção das animações, modifique os pontos de vida da unidade ou envie seu próprio vetor de sprites."
     article_editor_prefix: "Encontrou algo errado na nossa documentação? Gostaria de criar algumas instruções para suas próprias criações? Dê uma olhada em"
     article_editor_suffix: "e ajude os jogadores do CodeCombat a aproveitar o máximo de seu jogo."
     find_us: "Encontre-nos nestes sites"
@@ -738,21 +738,21 @@
     systems: "Sistemas"
     component: "Componente"
     components: "Componentes"
-#    thang: "Thang"
-#    thangs: "Thangs"
+    thang: "Thang"
+    thangs: "Thangs"
     level_session: "Sua Sessão"
     opponent_session: "Sessão do Oponente"
     article: "Artigo"
     user_names: "Nomes de Usuários"
-#    thang_names: "Thang Names"
+    thang_names: "Nome do Thang"
     files: "Arquivos"
     top_simulators: "Top Simuladores"
     source_document: "Documento da Fonte"
     document: "Documento"
-#    sprite_sheet: "Sprite Sheet"
+    sprite_sheet: "Folha de Sprites"
     employers: "Empregadores"
     candidates: "Candidatos"
-#    candidate_sessions: "Candidate Sessions"
+    candidate_sessions: "Sessão do Candidato"
     user_remark: "Observação do Usuário"
     user_remarks: "Observações do Usuário"
     versions: "Versões"
@@ -1050,4 +1050,4 @@
     av_other_debug_base_url: "Base (para debugar base.jade)"
     u_title: "Lista de Usuários"
     lg_title: "Últimos Jogos"
-#    clas: "CLAs"
+    clas: "CLAs"


Update pt-BR.coffee (#3830)

Update pt-BR.coffee (#3830)

--- app/locale/pt-BR.coffee
+++ app/locale/pt-BR.coffee
@@ -16,7 +16,7 @@

   new_home:
     slogan: "O jogo mais envolvente para aprender programação."
-#    classroom_edition: "Classroom Edition:"
+    classroom_edition: "Editar sala de aula:"
     learn_to_code: "Aprenda a programar:"
     teacher: "Professor"
     student: "Aluno"
@@ -25,13 +25,13 @@
     im_a_student: "Eu sou um Aluno"
     learn_more: "Aprenda mais"
     classroom_in_a_box: "Uma sala de aula in-a-box para o ensino de ciência da computação."
-#    codecombat_is: "CodeCombat is a platform for students to learn computer science while playing through a real game."
-#    our_courses: "Our courses have been specifically playtested to excel in the classroom, even by teachers with little to no prior programming experience."
+    codecombat_is: "CodeCombat é uma plataforma para estudantes aprenderem ciência da computação através de um jogo real."
+    our_courses: "Nossos cursos foram pensados especificamente para o uso em sala de aula, mesmo para professores com pouco conhecimento prévio em programação."
     top_screenshots_hint: "Alunos escrevem seus códigos e veem suas mudanças em tempo real."
     designed_with: "Projetado com professores em mente"
     real_code: "Código escrito, de verdade"
     from_the_first_level: "a partir do primeiro nível"
-#    getting_students: "Getting students to typed code as quickly as possible is critical to learning programming syntax and proper structure."
+    getting_students: "Fazer os estudantes digitarem o código o mais rapido possível é fundamental para aprender a sintaxe de programação e estrurutura apropriada."
     educator_resources: "Recursos do educador"
     course_guides: "e guia dos cursos"
 #    teaching_computer_science: "Teaching computer science does not require a costly degree, because we provide tools to support educators of all backgrounds."


Correct endianness in Login7 payload test to match the previous endian correction in the Login payload (thus fixing broken test case).

--- test/unit/login7-payload-test.coffee
+++ test/unit/login7-payload-test.coffee
@@ -32,7 +32,7 @@

   test.strictEqual(payload.data.length, expectedLength)

-  passwordStart = payload.data.readUInt16BE(4 + 32 + (2 * 4))
+  passwordStart = payload.data.readUInt16LE(4 + 32 + (2 * 4))
   passwordEnd = passwordStart + (2 * loginData.password.length)
   passwordExpected = new Buffer([0xa2, 0xa5, 0xd2, 0xa5])
   test.ok(payload.data.slice(passwordStart, passwordEnd).equals(passwordExpected))


selector: total test coverage

selector: total test coverage

--- test/spec/selector.coffee
+++ test/spec/selector.coffee
@@ -10,6 +10,9 @@
         el = $('#hello')
         assert.lengthOf el, 1
         assert el.length is 1, "Has one element"
+
+        el = $('#no-exists')
+        assert.lengthOf el, 0, "It has no elements"

     test 'class query', ->
         el = $('.a')
@@ -27,9 +30,67 @@
     test 'multiple results', ->
         el = $('#test li')
         assert.lengthOf el, 3, "It has 3 elements"
+
+    test 'matches error', ->
+        el = $()
+        el.elements = [{}]
+        el._update()
+
+        assert.lengthOf el.filter(), 0, "matches filter only elements"
+
+    test 'matches fallback', ->
+        # this test is really dont cool
+        util = $.require('util')
+
+        parent = document.createElement('div')
+        children_foo = document.createElement('div')
+        children_foo.className = 'foo'
+        children = document.createElement('div')
+        parent.appendChild children_foo
+        parent.appendChild children
+        el = $(parent)
+
+        prefix = util.prefix
+        util.prefix = -> return false
+
+        filter_div = el.filter('div')
+        filter_foo = el.children().filter('.foo')
+
+        util.prefix = prefix # restore prefix
+
+        assert.deepEqual filter_div.elements, [parent], "Remains the parent"
+        assert.deepEqual filter_foo.elements, [children_foo], "Remains the parent"

+suite 'Traversal methods', ->
+    test 'find', ->
+        all = $('*')
+        list = all.find('.list li')
+        assert.deepEqual list.get(), list_items().get(), "Gets the list items"

-suite 'Traversal methods', ->
+    test 'find in one', ->
+        doc = $(document)
+        list = doc.find('.list li')
+        assert.deepEqual list.get(), list_items().get(), "Gets the list items"
+
+    test 'filter', ->
+        all = $('*')
+        list = all.filter('.list li')
+        assert.deepEqual list.get(), list_items().get(), "Filter the list items"
+
+        nothing = all.filter('.nothing-with-this')
+        assert.equal nothing.length, 0, "Filter should returns nothing"
+
+        assert.deepEqual all, $('*'), "Doesnt affect the original"
+
+    test 'is', ->
+        doc = $(document)
+        assert.isTrue doc.is(document), "Document is document"
+
+        list = list_items()
+        assert.isTrue list.is('li'), "Filter the list items"
+
+        all = $('*')
+        assert.isTrue all.is(list_items()), "Filter the list items with Rye instance"

     test 'add multiple (Rye)', ->
         list = list_items()
@@ -59,6 +120,18 @@
         assert list3.length is 3, "Length didn't change"
         assert.deepEqual list3.pluck('className'), ['a', 'b', 'c'], "Classes match"

+    test 'pluck node', ->
+        list = list_items()
+        first = $(list.get(0))
+        second = $(first.pluckNode('nextSibling'))
+        assert.equal second.get(0), list.get(1), "Walks to second element"
+
+    test 'pluck', ->
+        obj = $()
+        obj.elements[0] = fizz: 'buzz'
+        obj._update()
+        assert.deepEqual obj.pluck('fizz'), ['buzz'], "Plucks elements properties"
+
     test 'next', ->
         el = $('.a').next()
         assert el.length is 1, "One element found"
@@ -68,11 +141,6 @@
         el = $('.c').prev()
         assert el.length is 1, "One element found"
         assert el.get(0).className is 'b', "Previous element is .b"
-
-    test 'parent', ->
-        el = $('.a').parent()
-        assert el.length is 1, "One element found"
-        assert el.get(0).className is 'list', "Parent is .list"

     test 'first', ->
         first = list_items().first()
@@ -90,11 +158,27 @@
         assert siblings.length is 2, "Two siblings"
         assert.deepEqual siblings.get().map((el) -> el.className), ['a', 'c']

+    test 'parent', ->
+        el = $('.a').parent()
+        assert el.length is 1, "One element found"
+        assert el.get(0).className is 'list', "Parent is .list"
+
+    test 'parents', ->
+        els = $('.a').parents()
+
+        assert.isTrue els.is('ul'), "Ul element found"
+        assert.isTrue els.is('body'), "Body always found"
+
     test 'closest', ->
         el = $('.a')
         closest = el.closest('ul')
         assert.lengthOf closest, 1
         assert.equal closest.get(0).className, 'list'
+
+        el = $('.a')
+        closest = el.closest('.a')
+        assert.lengthOf closest, 1
+        assert.equal closest.get(0).className, 'a'

         closest = el.closest('section#test')
         assert.lengthOf closest, 1
@@ -106,3 +190,10 @@

         closest = el.closest('bacon')
         assert.lengthOf closest, 0
+
+    test 'children', ->
+        list = $('.list').children()
+
+        assert.deepEqual list.elements, list_items().elements, "Ul element found"
+
+


Don't use computed renderers in GeoJsonDataSource

--- bokehjs/src/coffee/models/sources/geojson_data_source.coffee
+++ bokehjs/src/coffee/models/sources/geojson_data_source.coffee
@@ -8,18 +8,15 @@
   type: 'GeoJSONDataSource'

   @define {
-      geojson: [ p.Any     ] # TODO (bev)
-    }
-
-  # TODO (bev) investigate, exists on python side
-  # nonserializable_attribute_names: () ->
-  #   super().concat(['data'])
+    geojson: [ p.Any     ] # TODO (bev)
+  }

   initialize: (options) ->
     super(options)
-    @geojson_to_column_data() # this just validates the initial geojson value
-    @define_computed_property('data', @geojson_to_column_data, true)
-    @add_dependencies('data', this, ['geojson'])
+    @_update_data()
+    @listenTo(@, 'change:geojson', () => @_update_data())
+
+  _update_data: () -> @data = @geojson_to_column_data()

   _get_new_list_array: (length) ->
     array = new Array(length)
@@ -32,7 +29,7 @@
     return nan_array

   _flatten_function: (accumulator, currentItem) ->
-      return accumulator.concat([[NaN, NaN, NaN]]).concat(currentItem)
+    return accumulator.concat([[NaN, NaN, NaN]]).concat(currentItem)

   _add_properties: (item, data, i, item_count) ->
     for property of item.properties


fixed indentation

fixed indentation

--- bokehjs/src/coffee/models/sources/geojson_data_source.coffee
+++ bokehjs/src/coffee/models/sources/geojson_data_source.coffee
@@ -150,7 +150,7 @@
         if item.type == 'Feature'
           @_add_properties(item, data, arr_index, item_count)

-      arr_index += 1
+        arr_index += 1

     return data


adding other implicit indentation/call/object test.

--- test/test_literals.coffee
+++ test/test_literals.coffee
@@ -193,4 +193,15 @@
 ok (key for key of obj.red).length is 2
 ok obj.red.orange.yellow.green is 'blue'
 ok obj.red.indigo is 'violet'
-ok obj.misdent.toString() is ',,,'+ok obj.misdent.toString() is ',,,'
+
+second = (x, y) -> y
+obj = then second 'the',
+  one: 1
+  two:
+    three: ->
+      four five,
+        six: seven
+  three: 3
+
+ok obj.three is 3


Skip the flexbox-repaint-hack when seeking editor pane with ::parents

--- src/editor-view.coffee
+++ src/editor-view.coffee
@@ -1070,7 +1070,7 @@
   #
   # Returns a {Pane}.
   getPane: ->
-    @parent('.item-views').parent('.pane').view()
+    @parents('.pane').view()

   remove: (selector, keepData) ->
     return super if keepData or @removed


:art:

:art:

--- lib/notification-issue.coffee
+++ lib/notification-issue.coffee
@@ -7,6 +7,8 @@
 UserUtilities = require './user-utilities'

 TITLE_CHAR_LIMIT = 100 # Truncate issue title to 100 characters (including ellipsis)
+
+FileURLRegExp = new RegExp('file://\w*/(.*)')

 module.exports =
 class NotificationIssue
@@ -183,11 +185,11 @@
         packagePaths[packageName] = fs.realpathSync(packagePath)

     getPackageName = (filePath) =>
-      filePath = /(\((.+?):\d+|\((.+)\)|(.+))/.exec(filePath)[1]
+      filePath = /\((.+?):\d+|\((.+)\)|(.+)/.exec(filePath)[0]

       # Stack traces may be a file URI
-      if /file:\/\/(\w*)\/(.*)/.test(filePath)
-        filePath = /file:\/\/(\w*)\/(.*)/.exec(filePath)[2]
+      if match = FileURLRegExp.exec(filePath)
+        filePath = match[1]

       if path.isAbsolute(filePath)
         for packName, packagePath of packagePaths


Onboarding: improved koding bot

Onboarding: improved koding bot

--- client/Social/Activity/views/privatemessage/kodingbot.coffee
+++ client/Social/Activity/views/privatemessage/kodingbot.coffee
@@ -1,34 +1,49 @@
 class KodingBot extends KDObject
+
+  CHANNEL_ID = null
+
+  constructor: ->
+
+    super
+
+    CHANNEL_ID = @getDelegate().getData().id
+
+  updateProfile = (key, value, callback) ->
+    me = KD.whoami()
+    oldValue = me.profile[key]
+    # do not do anything if current firstname and lastname is same
+    return if oldValue is value
+
+    options = {}
+    options["profile.#{key}"] = value
+
+    me.modify options, (err)->
+      return notify err.message  if err
+      callback()

   questionMap =
     'Name?' :
       fn    : (firstName)->
-        me = KD.whoami()
-        {profile:{firstName:oldFirstName}} = me
-        # do not do anything if current firstname and lastname is same
-        return if oldFirstName is firstName
-
-        me.modify {
-          "profile.firstName" : firstName
-        }, (err)->
-          return notify err.message  if err
-          new KDNotificationView title : "Nice to meet you #{firstName}! What is your last name?"
+        updateProfile 'firstName', firstName, =>
+          KD.singletons.socialapi.message.sendPrivateMessage
+            channelId : CHANNEL_ID
+            body : "Nice to meet you #{firstName}! What is your last name?"
+          , log

     'Last name?' :
       fn    : (lastName)->
-        me = KD.whoami()
-        {profile:{lastName:oldLastName}} = me
-        # do not do anything if current firstname and lastname is same
-        return if oldLastName is lastName
+        updateProfile 'lastName', lastName, ->
+          KD.singletons.socialapi.message.sendPrivateMessage
+            channelId : CHANNEL_ID
+            body : "Great, Welcome #{KD.utils.getFullnameFromAccount KD.whoami()}!"
+          , log

-        me.modify {
-          "profile.lastName" : lastName
-        }, (err)->
-          return notify err.message  if err
-          new KDNotificationView title : "Alright last name is set..."
+    # 'Password?' :
+    #   fn    : (lastName)->
+    #     updateProfile 'firstName', firstname, ->
+    #       new KDNotificationView title : "Alright last name is set..."

   process : (question, answer) ->
-
     if questionMap[question.body]
       {fn} = questionMap[question.body]
       fn answer


sidebar: add css class to show selected stack status

Signed-off-by: Umut Sirin <4055abbc0e40a1254e715b952ccd414607e0b365@gmail.com>

--- client/app/lib/sidebar/components/ownedresourceheader.coffee
+++ client/app/lib/sidebar/components/ownedresourceheader.coffee
@@ -10,13 +10,14 @@

   render: ->

-    { title, onTitleClick, unreadCount, onMenuIconClick } = @props
+    { title, onTitleClick, unreadCount, onMenuIconClick, selected } = @props

     className = cx ['SidebarSection-header', {
       'unread': !!unreadCount
+      'active': !!selected
     }]

-    <header className='SidebarSection-header'>
+    <header className={className}>
       <h4 className='SidebarSection-headerTitle'>

         <Link onClick={onTitleClick}>{title}</Link>


Arrange setTimeout and research when error

--- scripts/amazon-ec.coffee
+++ scripts/amazon-ec.coffee
@@ -42,10 +42,13 @@
       'Sort':'daterank',
       'ItemPage': page
     }).then((response) ->
-      console.log "Raw response body: ", response.responseBody
+      console.log "debug: Raw response body: ", response.responseBody

       # 処理が速すぎるとときどき AWS API がエラーとなるため処理終了
       if response.result.ItemSearchResponse is undefined
+        console.log 'error: 処理が速すぎてエラーになりました'
+        # 処理がたまらないように余裕を持たせる
+        setTimeout((() -> amazonSearch.search(query, isKindle, page , callback, nothingCallBack)), 60000)
         return

       baseResult = response.result.ItemSearchResponse.Items[0]
@@ -67,7 +70,7 @@
         }

       if page < totalPages and page < 10
-        setTimeout((() -> this.search), 5000, query, isKindle, page + 1, callback, nothingCallBack)
+        setTimeout((() -> amazonSearch.search(query, isKindle, page + 1 , callback, nothingCallBack)), 5000)

     ).catch((err) ->
       console.log("error:", err)
@@ -143,6 +146,8 @@
     console.log users

     i = 1
+    timeWait = 0
+
     while user = users[i]
       i++
       console.log(user.name)
@@ -150,8 +155,9 @@
       stores =  robot.brain.get(user.name)

       for store in stores
-        nexWeekSearch(response, store.title, store.kindle)
-        tomorrowSearch(response, store.title, store.kindle)
+        timeWait += 10000
+        setTimeout(nexWeekSearch, timeWait, msg, store.title, store.kindle)
+        setTimeout(tomorrowSearch, timeWait + 5000, msg, store.title, store.kindle)

   # 起動時にクーロン設定
   # *(sec) *(min) *(hour) *(day) *(month) *(day of the week)


:art: Beautify EditorLinter::constructor a bit

--- lib/editor-linter.coffee
+++ lib/editor-linter.coffee
@@ -16,10 +16,10 @@
       @editor.onDidChangeCursorPosition ({newBufferPosition}) =>
         @linter.views.updateBubble(newBufferPosition)
     )
-    return unless @linter.lintOnFly
-    @subscriptions.add(
-      @editor.onDidStopChanging => @lint(true) if @linter.lintOnFly
-    )
+    if @linter.lintOnFly
+      @subscriptions.add(
+        @editor.onDidStopChanging => @lint(true) if @linter.lintOnFly
+      )

   # Called on package deactivate
   destroy: ->


fine tune clam-down triggers

fine tune clam-down triggers

--- scripts/calm-down.coffee
+++ scripts/calm-down.coffee
@@ -16,12 +16,13 @@

   robot.respond /manatee|calm( me)?/i, (msg) -> msg.send manatee()

-  robot.hear /calm down|simmer down|that escalated quickly|успокойся|не кипятись/i, (msg) ->
+  robot.hear /calm down|simmer down|that escalated quickly|успокойся|не кипятись|угомонись|остынь/i, (msg) ->
     msg.send manatee()

   unless process.env.HUBOT_LESS_MANATEES
     robot.hear ///
       (\b([A-Z]{2,}\s+)([A-Z]{2,})\b)|
       (\b[A-Z]{6,}\b)|
-      ([А-ЯЁ]{6,})
+      (\b([А-ЯЁ]{3,}\s+)([А-ЯЁ]{3,})\b)|
+      ([А-ЯЁ]{10,})
     ///, (msg) -> msg.send manatee()


remove commented tests

remove commented tests

--- bokehjs/test/models/glyphs/glyph.coffee
+++ bokehjs/test/models/glyphs/glyph.coffee
@@ -1,44 +0,0 @@
-{expect} = require "chai"
-utils = require "../../utils"
-
-{Collections} = utils.require "base"
-
-view_for = (model) ->
-  new model.default_view({model : model})
-
-describe "glyph", ->
-
-  # describe "units handling", ->
-  #   it "should default to 'data' for distances", ->
-  #     obj = Collections('AnnularWedge').create()
-  #     view = view_for(obj)
-  #     expect(view.distances.inner_radius.units).to.be.equal 'data'
-
-  #   it "should default to 'rad' for angles", ->
-  #     obj = Collections('AnnularWedge').create()
-  #     view = view_for(obj)
-  #     expect(view.angles.start_angle.units).to.be.equal 'rad'
-
-  #   it "should get the constructor-provided units for distances", ->
-  #     obj = Collections('AnnularWedge').create({ 'inner_radius' : { 'value' : 1, 'units' : 'screen' } })
-  #     view = view_for(obj)
-  #     expect(view.distances.inner_radius.units).to.be.equal 'screen'
-
-  #   it "should get the constructor-provided units for angles", ->
-  #     obj = Collections('AnnularWedge').create({ 'start_angle' : { 'value' : 60, 'units' : 'deg' } })
-  #     view = view_for(obj)
-  #     expect(view.angles.start_angle.units).to.be.equal 'deg'
-
-  #   it "should update units when a distance value is set", ->
-  #     obj = Collections('AnnularWedge').create()
-  #     view = view_for(obj)
-  #     expect(view.distances.inner_radius.units).to.be.equal 'data'
-  #     obj.set({ 'inner_radius' : { 'value' : 1, 'units' : 'screen' } })
-  #     expect(view.distances.inner_radius.units).to.be.equal 'screen'
-
-  #   it "should update units when an angle value is set", ->
-  #     obj = Collections('AnnularWedge').create()
-  #     view = view_for(obj)
-  #     expect(view.angles.start_angle.units).to.be.equal 'rad'
-  #     obj.set({ 'start_angle' : { 'value' : 60, 'units' : 'deg' } })
-  #     expect(view.angles.start_angle.units).to.be.equal 'deg'


removed mouseclick binding

removed mouseclick binding

--- src/game_object.coffee
+++ src/game_object.coffee
@@ -55,13 +55,7 @@

   self.trigger('create') unless I.created
   I.created = true
-
-  #TODO: Move this
-  $(document).bind 'mousedown', (event) ->
-    if (I.x <= event.offsetX <= I.x + I.width) &&
-    (I.y <= event.offsetY <= I.y + I.height)
-      self.trigger('click')
-
+
   self

 GameObject.construct = (entityData) ->


Guard against failure.

Guard against failure.

Since these are executing in the page's context, they could break the
page if they were to fail (for whatever reason).  So we add some
(possibly unnecessary) guards, just in case.

--- content_scripts/injected.coffee
+++ content_scripts/injected.coffee
@@ -10,8 +10,9 @@
   _addEventListener = Element::addEventListener

   Element::addEventListener = (type, listener, useCapture) ->
-    @setAttribute vimiumOnClickAttributeName, "" if type == "click"
-    _addEventListener.apply this, arguments
+    if type == "click"
+      try @setAttribute vimiumOnClickAttributeName, ""
+    _addEventListener?.apply this, arguments

 script = document.createElement "script"
 script.textContent = "(#{injectedCode.toString()})('#{vimiumOnClickAttributeName}')"


Add default config

Add default config

--- lib/logger-config.coffee
+++ lib/logger-config.coffee
@@ -1 +1,8 @@
-module.exports = {}+# Configuration class.
+class Config
+  max: 10
+  outputs: ['console']
+if typeof module is 'undefined' and typeof window isnt 'undefined'
+  window.Config  = Config
+else
+  module.exports = Config


use a similar passes.forEach construct in this file as we do in closure-conversion.coffee.

--- lib/optimizations.coffee
+++ lib/optimizations.coffee
@@ -5,7 +5,7 @@

 { TreeTransformer } = require 'nodevisitor'

-{ create_intrinsic } = require 'echo-util'
+{ create_intrinsic, is_intrinsic } = require 'echo-util'

 #
 # EqIdioms checks for the following things:
@@ -139,7 +139,7 @@

                 # now make sure the init block initializes update_identifier_name

-                if exp.init.type isnt VariableDeclaration and exp.init.type isnt AssignmentExpression
+                if exp.init.type isnt VariableDeclaration and exp.init.type isnt syntax.AssignmentExpression
                         return super

                 if exp.init.type is VariableDeclaration
@@ -157,10 +157,17 @@

                 # if we've made it here, we have an expression we can deal with.
 ###
+
+passes = [
+        EqIdioms
+        ]

 exports.run = (tree) ->

-        eq_idioms = new EqIdioms
-        tree = eq_idioms.visit tree
-
+        passes.forEach (passType) ->
+                pass = new passType
+                tree = pass.visit tree
+                debug.log 2, "after: #{passType.name}"
+                debug.log 2, -> escodegen.generate tree
+
         return tree


Settings for which things to sync. Closes #54

--- lib/sync-settings.coffee
+++ lib/sync-settings.coffee
@@ -16,16 +16,43 @@
       description: 'Your personal GitHub access token'
       type: 'string'
       default: ''
+      order: 1
     gistId:
       description: 'ID of gist to use for configuration storage'
       type: 'string'
       default: ''
+      order: 2
+    syncSettings:
+      type: 'boolean'
+      default: true
+      order: 3
+    syncPackages:
+      type: 'boolean'
+      default: true
+      order: 4
+    syncKeymap:
+      type: 'boolean'
+      default: true
+      order: 5
+    syncStyles:
+      type: 'boolean'
+      default: true
+      order: 6
+    syncInit:
+      type: 'boolean'
+      default: true
+      order: 7
+    syncSnippets:
+      type: 'boolean'
+      default: true
+      order: 8
     extraFiles:
       description: 'Comma-seperated list of files other than Atom\'s default config files in ~/.atom'
       type: 'array'
       default: []
       items:
         type: 'string'
+      order: 9

   activate: ->
     GitHubApi ?= require 'github'
@@ -38,19 +65,18 @@
   serialize: ->

   backup: (cb=null) ->
-    files =
-      "settings.json":
-        content: JSON.stringify(atom.config.settings, @filterSettings, '\t')
-      "packages.json":
-        content: JSON.stringify(@getPackages(), null, '\t')
-      "keymap.cson":
-        content: (@fileContent atom.keymaps.getUserKeymapPath()) ? "# keymap file (not found)"
-      "styles.less":
-        content: (@fileContent atom.styles.getUserStyleSheetPath()) ? "// styles file (not found)"
-      "init.coffee":
-        content: (@fileContent atom.config.configDirPath + "/init.coffee") ? "# initialization file (not found)"
-      "snippets.cson":
-        content: (@fileContent atom.config.configDirPath + "/snippets.cson") ? "# snippets file (not found)"
+    if atom.config.get('sync-settings.syncSettings')
+      files["settings.json"] = content: JSON.stringify(atom.config.settings, @filterSettings, '\t')
+    if atom.config.get('sync-settings.syncPackages')
+      files["packages.json"] = content: JSON.stringify(@getPackages(), null, '\t')
+    if atom.config.get('sync-settings.syncKeymap')
+      files["keymap.cson"] = content: (@fileContent atom.keymaps.getUserKeymapPath()) ? "# keymap file (not found)"
+    if atom.config.get('sync-settings.syncStyles')
+      files["styles.less"] = content: (@fileContent atom.styles.getUserStyleSheetPath()) ? "// styles file (not found)"
+    if atom.config.get('sync-settings.syncInit')
+      files["init.coffee"] = content: (@fileContent atom.config.configDirPath + "/init.coffee") ? "# initialization file (not found)"
+    if atom.config.get('sync-settings.syncSnippets')
+      files["snippets.cson"] = content: (@fileContent atom.config.configDirPath + "/snippets.cson") ? "# snippets file (not found)"

     for file in atom.config.get('sync-settings.extraFiles') ? []
       ext = file.slice(file.lastIndexOf(".")).toLowerCase()
@@ -95,22 +121,22 @@
       for own filename, file of res.files
         switch filename
           when 'settings.json'
-            @applySettings '', JSON.parse(file.content)
+            @applySettings '', JSON.parse(file.content) if atom.config.get('sync-settings.syncSettings')

           when 'packages.json'
-            @installMissingPackages JSON.parse(file.content), cb
+            @installMissingPackages JSON.parse(file.content), cb if atom.config.get('sync-settings.syncPackages')

           when 'keymap.cson'
-            fs.writeFileSync atom.keymaps.getUserKeymapPath(), file.content
+            fs.writeFileSync atom.keymaps.getUserKeymapPath(), file.content if atom.config.get('sync-settings.syncKeymap')

           when 'styles.less'
-            fs.writeFileSync atom.styles.getUserStyleSheetPath(), file.content
+            fs.writeFileSync atom.styles.getUserStyleSheetPath(), file.content if atom.config.get('sync-settings.syncStyles')

           when 'init.coffee'
-            fs.writeFileSync atom.config.configDirPath + "/init.coffee", file.content
+            fs.writeFileSync atom.config.configDirPath + "/init.coffee", file.content if atom.config.get('sync-settings.syncInit')

           when 'snippets.cson'
-            fs.writeFileSync atom.config.configDirPath + "/snippets.cson", file.content
+            fs.writeFileSync atom.config.configDirPath + "/snippets.cson", file.content if atom.config.get('sync-settings.syncSnippets')

           else fs.writeFileSync "#{atom.config.configDirPath}/#{filename}", file.content


change debounce action delay to 66ms (15fps)

--- src/kapi-scroll.coffee
+++ src/kapi-scroll.coffee
@@ -78,11 +78,11 @@
                 actionProp.down.apply(c) if actionProp.down

               actionFrameIdx = ++idx
-
+
           prevScrollY = scrollY

-        actionsUpdate = _.debounce(actionsUpdate, 33, {leading: true, maxWait: 33})
+        actionsUpdate = _.debounce(actionsUpdate, 66, {leading: true, maxWait: 66})

         update = ->


SetHakochabimGeonim now uses the stricter of 2 calculations of 13.5 minutes: daytime minutes and nighttime minutes

--- source/javascripts/site/zmanim.coffee
+++ source/javascripts/site/zmanim.coffee
@@ -36,7 +36,13 @@
   hadlakatNerot: -> # TODO: test
     if (new HebrewDate(@gregorianDate)).hasHadlakatNerot() then moment(@sunset()).subtract(18, 'minutes').seconds(0) else null
   sunset: -> @_sunset ?= moment(@zmanim.sunset)
-  setHaKochabimGeonim: -> @_setHaKochabimGeonim ?= @shaaZemaniGra(12.225).add(1, 'minute')
+  setHaKochabimGeonim: -> @_setHaKochabimGeonim ?= (
+    time = @shaaZemaniGra(12.225)
+    timeSinceSunset = time.diff(@sunset()) / 1000.0 / 60.0
+    timeSinceSunset = 27 - timeSinceSunset if timeSinceSunset < 13.5
+    time = moment(@sunset()).add(timeSinceSunset, 'minutes')
+    time.seconds(60)
+  )
   setHaKochabim3Stars: -> @_setHaKochabim3Stars ?= moment(@zmanim.setHaKochabim)

 (exports ? this).Zmanim = Zmanim


Light refactoring

Light refactoring

--- src/sc/stream.coffee
+++ src/sc/stream.coffee
@@ -1,26 +1,30 @@
 window.SC = SC.Helper.merge SC || {},
   _audiomanagerPath: "/audiomanager"
   _audiomanagerScriptPath: "/audiomanager.js"
-  _players:  []

   whenStreamingReady: (callback) ->
     SC.Loader.packages.streaming.whenReady callback

-  _setOnPositionListenersForComments: (player, comments, callback) ->
-    window.group = SC.Helper.groupBy(comments, "timestamp")
-    window.player = player
-    player.on 'positionChange', (current, loaded, duration) =>
-      lookup = parseInt(current, 10).toString()
-      callback(window.group[lookup]) if window.group.hasOwnProperty(lookup)
+  _isNumericId: (idOrUrl) ->
+    return idOrUrl.toString().match /^\d.*$/

   _prepareStreamUrl: (idOrUrl) ->
-    if idOrUrl.toString().match /^\d.*$/
-      return "/tracks/#{idOrUrl}/streams"
+    return "/tracks/#{idOrUrl}/streams" if @_isNumericId(idOrUrl)
     uri = new SC.URI(idOrUrl, {decodeQuery: true})
     suffix = "/streams"
     if uri.path.indexOf(suffix, uri.path.length - suffix.length) == -1
       uri.path += suffix
     uri.toString()
+
+  _setOnPositionListenersForComments: (player, comments, callback) ->
+    player.on 'positionChange', (current, loaded, duration) =>
+      collection = []
+      for key in Object.keys(comments)
+        break if key > parseInt(current, 10)
+        collection.push(comments[key])
+        delete comments[key]
+      collection = [].concat.apply([], collection)
+      callback(collection)

   stream: (idOrUrl, optionsOrCallback, callback) ->
     a = SC.Helper.extractOptionsAndCallbackArguments(optionsOrCallback, callback)
@@ -33,33 +37,21 @@
         callback(player) if callback?
         player

-      url = if idOrUrl.toString().match /^\d.*$/ then "/tracks/" + idOrUrl else idOrUrl
+      url = if @_isNumericId(idOrUrl) then "/tracks/" + idOrUrl else idOrUrl
       streamsUrl = @_prepareStreamUrl(url)

-      SC.get url, (track) ->
-        SC.get streamsUrl, (streams) ->
+      SC.get url, (track) =>
+        options.duration = track.duration
+        SC.get streamsUrl, (streams) =>
           options.src = streams.http_mp3_128_url || streams.rtmp_mp3_128_url
-          options.duration = track.duration
           if ontimedcommentsCallback = options.ontimedcomments
             delete options.ontimedcomments
             SC._getAll url + "/comments", (comments) =>
               player = createAndCallback(options)
               group = SC.Helper.groupBy(comments, "timestamp")
-              player.on 'positionChange', (current, loaded, duration) =>
-                collection = []
-                for key in Object.keys(group)
-                  break if key > parseInt(current, 10)
-                  collection.push(group[key])
-                  delete group[key]
-                collection = [].concat.apply([], collection)
-                ontimedcommentsCallback(collection)
+              @_setOnPositionListenersForComments(player, group, ontimedcommentsCallback)
           else
             createAndCallback(options)
-
-  streamStopAll: ->
-    if window.audioManager?
-      for player in window.audioManager._players
-        player.pause()

 SC.Loader.registerPackage new SC.Loader.Package "streaming", ->
   audioManagerURL = SC._baseUrl + SC._audiomanagerPath


Only grow the circle by the actual width.

--- source/javascripts/elements/circle.coffee
+++ source/javascripts/elements/circle.coffee
@@ -10,7 +10,7 @@
       if @trackingCircle
         offset = @canvas.el.offset()
         offsetX = info.e.pageX - offset.left
-        radius = offsetX - @options.coords[0]
+        radius = (offsetX - @options.coords[0]) / 2

         if radius > 0
           @circle.setRadius(radius)


Firefox does not like setting range to same pos

Fixes #181

--- src/selection.coffee
+++ src/selection.coffee
@@ -56,7 +56,7 @@
   shiftAfter: (index, length, fn) ->
     range = this.getRange()
     fn()
-    if range?
+    if range? and length != 0
       range.shift(index, length)
       this.setRange(range, 'silent')


_callOutstandingCallbacks typo

_callOutstandingCallbacks typo

--- src/lib/Channel.coffee
+++ src/lib/Channel.coffee
@@ -56,7 +56,7 @@
       cb("state isn't closed.  not opening channel") if cb?

   reset: (cb)=>
-    @_callOutstadingCallbacks("Channel Opening or Reseting")
+    @_callOutstandingCallbacks("Channel Opening or Reseting")

     # if our state is closed and either we arn't a transactional channel (queue, exchange declare etc..)
     # or we're within our acceptable time window for this queue
@@ -194,7 +194,7 @@
         throw new Error("a task was queue with an unknown type of #{type}")

-  _callOutstadingCallbacks: (message)=>
+  _callOutstandingCallbacks: (message)=>
     outStandingCallbacks = @waitingCallbacks
     @waitingCallbacks    = {}

@@ -220,7 +220,7 @@
         @state = 'closed'

         @_channelClosed("Channel closed")
-        @_callOutstadingCallbacks({msg: "Channel closed"})
+        @_callOutstandingCallbacks({msg: "Channel closed"})

       when methods.channelClose
         @connection.channelManager.channelClosed(channel)
@@ -233,7 +233,7 @@
           @callbackForMethod(methods["#{closingMethod}Ok"])(args) #this would be the error

         @_channelClosed({msg: "Server closed channel", error: args})
-        @_callOutstadingCallbacks("Channel closed by server #{JSON.stringify args}")
+        @_callOutstandingCallbacks("Channel closed by server #{JSON.stringify args}")

       when methods.channelOpenOk
         @state = 'open'


[neo4j] added topic following support

[neo4j] added topic following support

--- server/lib/server/graph/graph.coffee
+++ server/lib/server/graph/graph.coffee
@@ -153,7 +153,7 @@
     query = [
       'start koding=node:koding(id={groupId})'
       'MATCH koding-[:member]->followees<-[r:follower]-follower'
-      'where followees.name="JAccount" and follower.name="JAccount" and r.createdAt > {startDate} and r.createdAt < {endDate}'
+      'where followees.name="JAccount" and r.createdAt > {startDate} and r.createdAt < {endDate}'
       'return r,followees, follower'
       'order by r.createdAt DESC'
       'limit 10'


fix RAM problem for ubuntu 15.10, refs #339

--- server/lib/memory.coffee
+++ server/lib/memory.coffee
@@ -4,7 +4,7 @@

 ControllerClient = require("cozy-clients").ControllerClient

-freeMemCmd = "free | grep cache: | cut -d':' -f2 | sed -e 's/^ *[0-9]* *//'"
+freeMemCmd = "free | grep /cache | cut -d':' -f2 | sed -e 's/^ *[0-9]* *//'"

 # Utilities to get memory consumption and disk usage.


Tiny style patch from post-merge review on #78

--- tests/request.spec.coffee
+++ tests/request.spec.coffee
@@ -258,15 +258,16 @@

 			beforeEach ->
 				requestsSeen = 0
-				fetchMock.get 'https://example.com/initially-failing', ->
+				fetchMock.get 'https://example.com/initially-failing', Promise.method ->
 					requestsSeen += 1
 					if requestsSeen <= 2
-						Promise.reject(new Error('low-level network error'))
+						throw new Error('low-level network error')
 					else
-						Promise.resolve
+						return {
 							body: result: 'success'
 							headers:
 								'Content-Type': 'application/json'
+						}

 			it 'should fail by default', ->
 				promise = request.send


Adapt activearea before unit bounds.

Adapt activearea before unit bounds.

--- src/map-view.coffee
+++ src/map-view.coffee
@@ -131,6 +131,7 @@
             markers = unitsWithLocation.map (unit) => @createMarker(unit, options?.marker)
             latLngs = _(markers).map (m) => m.getLatLng()
             unless options?.keepViewport
+                MapView.setMapActiveAreaMaxHeight()
                 @map.adaptToLatLngs latLngs
             @allMarkers.addLayers markers


added fix for facebox margin issue

added fix for facebox margin issue

--- src/lib/options.coffee
+++ src/lib/options.coffee
@@ -882,4 +882,8 @@
       $('#feature_shortcut_txt').html ext.SHORTCUT_MODIFIERS
     # Initialize all faceboxes.
     $('a[facebox]').click ->
-      $.facebox div: $(this).attr 'facebox'+      $.facebox div: $(this).attr 'facebox'
+    facebox = $ '#facebox > .popup > .content'
+    $(document).bind 'reveal.facebox', ->
+      facebox.css 'margin-right',
+        if facebox.find('> .template').length then '0' else ''


Properly stage deleted files

Properly stage deleted files

--- lib/git-changes.coffee
+++ lib/git-changes.coffee
@@ -13,6 +13,7 @@
 module.exports =
 class GitChanges
   changes: {}
+  statuses: {}

   constructor: ->
     @repoPath = atom.project.getPaths()[0]
@@ -52,14 +53,24 @@
       @stagedPromise.catch (e) -> console.log e
       @unstagedPromise.catch (e) -> console.log e

-      repo.getStatus()
+      repo.getStatus().then (statuses) =>
+        for status in statuses
+          @statuses[status.path()] = status
+
+        statuses

   stagePath: (path) ->
     @stageAllPaths([path])

   stageAllPaths: (paths) ->
-    @indexPromise.then (index) ->
-      index.addByPath(path) for path in paths
+    @indexPromise.then (index) =>
+      for path in paths
+        status = @statuses[path]
+        if status.statusBit() & Git.Status.STATUS.WT_DELETED
+          index.removeByPath(path)
+        else
+          index.addByPath(path)
+
       index.write()
       new Promise (resolve, reject) =>
         process.nextTick =>


kill disabling of key events until I can sort out this bug.

--- app/assets/javascripts/ample_assets/classes/ample_assets.js.coffee
+++ app/assets/javascripts/ample_assets/classes/ample_assets.js.coffee
@@ -418,7 +418,8 @@
     down = 40
     escape = 27
     $(document).keydown (e) =>
-      return unless @keys_enabled
+      #console.log('keydown')
+      #return unless @keys_enabled or @active_panel
       switch e.keyCode
         when previous
           $(@active_panel).amplePanels('previous')


add documentation to ample_assets.js.coffee

--- app/assets/javascripts/ample_assets/classes/ample_assets.js.coffee
+++ app/assets/javascripts/ample_assets/classes/ample_assets.js.coffee
@@ -1,20 +1,33 @@
+# **AmpleAssets** is drag and drop file management for Rails applications.
+#
+#     ample_assets.coffee v1.0
+#     http://github.com/ample/ample_assets
+#     Copyright (c) Ample, http://helloample.com
+#     MIT-style license: http://pipwerks.mit-license.org/
+#
 class window.AmpleAssets

+  # Standard issue constructor method, called upon object instantiation.
   constructor: (opts=undefined) ->
     @set_options(opts)
     @init()

+  # Triggers onInit method.
+  # Initialize product toolbar and drop targets.
   init: ->
     @options.onInit()
     @setup()
     @events()

+  # Setup global parameters & class options.
   set_options: (opts) ->
     @current = 0
     @keys_enabled = true
     @reloading = false
     @searching = false
-    ref = this
+    @loaded = false
+    ref = this
+    # Define defaults.
     default_options =
       debug: true
       expanded: false
@@ -62,14 +75,17 @@
         }
       ]

-    @loaded = false
+    # Override defaults with user defined options.
     @options = default_options
     for k of opts
       @options[k] = opts[k]

+  # Log debug output to JS console.
   log: (msg) ->
     console.log "ample_assets.log: #{msg}" if @options.debug

+  # Build structure and stylize layout of toolbar, setup drag, drop and search logic.
+  # Opens first tab if toolbar is expanded on init.
   setup: ->
     id = @options.id
     layout = Mustache.to_html(@tpl('layout'),{ id: id, pages: @get_pages(), tabs: @get_pages('tab') })
@@ -80,15 +96,15 @@
     @drag_drop()
     @search()
     @goto(0) if @options.expanded
-    $('body').bind 'ample_uploadify.complete', =>
-      @reload(0)
-
+
+  # Set initial styles on toolbar elements.
   style: ->
     @loading = $("##{@options.id}-tabs span.asset-loading")
     $("##{@options.id} .container").css('height',200)
     if @options.expanded
       $("##{@options.id}").css({height:@options.expanded_height});

+  # Reloads tab identified by `i`
   reload: (i) ->
     @log "reload(#{i})"
     @reloading = true
@@ -101,12 +117,14 @@
       @goto(i)
       @enable_panel(i)

+  # Empties the contents of the page identified by `i`
   empty: (i) ->
     @log "empty(#{i})"
     selector = "##{@options.id} .pages .page:nth-child(#{(i+1)})"
     selector += " ul" if @options.pages[i]['panels']
     $(selector).empty()

+  # Hide and deactivate current page, load next page identified by `i`
   goto: (i) ->
     @log "goto(#{i})"
     @show(i)
@@ -115,15 +133,18 @@
     @load(i) unless @already_loaded(i)
     @enable_panel(i) if @already_loaded(i)

+  # Hide all pages, show page identified by `i`
   show: (i) ->
     $("##{@options.id} .pages .page").hide()
     $("##{@options.id} .pages .page:nth-child(#{i+1}), ##{@options.id} .pages .page:nth-child(#{i+1}) ul").show()

+  # Implement drag & droppable instances, with appropriate callbacks.
   drag_drop: ->
     base_url = @options.base_url
     thumb_url = @options.thumb_url
     ref = this

+    # Note the use of liveDraggable here. See extended plugin at the bottom of this file.
     $(".draggable").liveDraggable
       appendTo: "body"
       helper: "clone"
@@ -144,7 +165,11 @@
         $(this).parent().children().first().val asset_id
         $(this).parent().find('a.asset-remove').removeClass('hide').show()

+  # Build html for modal windows wherein users can resize the asset's dimensions & geometry.
+  # Executes when dropping a file into a textarea. The first argument is the response
+  # from the droppable callbacks defined above.
   resize_modal: (el) ->
+    console.log el
     uid = $(el).attr("data-uid")
     size = $(el).attr("data-size")
     orientation = $(el).attr("data-orientation")
@@ -159,6 +184,7 @@
     html = Mustache.to_html(@tpl('drop'), opts)
     $.facebox("
#{html}
")

+  # Removes active state from all tabs, adds it back for tab identified by `i`
   activate: (i) ->
     @log "activate(#{i})"
     @current = i
@@ -166,18 +192,21 @@
     tabs.removeClass('on')
     tabs.eq(i).addClass('on')

+  # Highlight & load next tab (right) by incrementing `@current`
   next: ->
     if @current < @options.pages.length - 1
       @log "next()"
       @current += 1
       @goto(@current)

+  # Highlight & load previous tab (left) by decrementing `@current`
   previous: ->
     unless @current == 0
       @log "previous()"
       @current -= 1
       @goto(@current)

+  # Loops through all pages, generates HTML and returns concatenated string of everything.
   get_pages: (tpl = 'page') ->
     html = ''
     $.each @options.pages, (idx,el) =>
@@ -185,6 +214,7 @@
       html += Mustache.to_html @tpl(tpl), el
     html

+  # Expands and collapses asset toolbar.
   toggle: ->
     el = $("##{@options.id}")
     if @options.expanded
@@ -200,6 +230,7 @@
         @expand()
         @options.onExpand()

+  # Loads contents of page identified by `i`
   load: (i) ->
     @log "load(#{i})"
     ref = this
@@ -214,20 +245,25 @@
       $.get url, (response, xhr) ->
         ref.loading.hide()
         ref.options.pages[i]['loaded'] = true
+        # If response is empty, let users know by loading an empty notification.
         if $.trim(response) == '' || response.length == 0
           ref.options.pages[i]['last_request_empty'] = true
           ref.load_empty(i) if ref.reloading || !ref.options.pages[i]['panel_selector']
         else
           switch data_type
             when "json"
+              # Parse json for requests of that type.
               ref.load_json i, response
             when "html"
             else
+              # Parse html by default or for requests of that specific type.
               ref.load_html i, response
       , data_type
     else
+      # Notify console if we couldn't load a page due to a missing URL.
       @log "ERROR --> Couldn't load page because there was no url" unless @options.pages[i]['last_request_empty']

+  # For empty requests, insert notification text into page identified by `i`
   load_empty: (i) ->
     @log "load_empty(#{i})"
     empty = Mustache.to_html(@tpl('empty'))
@@ -237,6 +273,7 @@
     $('li.empty a').click =>
       @goto(@options.pages.length-2)

+  # Load html content returned as `response` by XHR request into page identified by `i`
   load_html: (i, response) ->
     @log "load(#{i}) html"
     selector = "##{@options.id} .pages .page:nth-child(#{(i+1)})"
@@ -244,6 +281,8 @@
     $(selector).html(response).show()
     @panels(i)

+  # Parse `response` as json data and build list-items for each element contained therein.
+  # This method assumes page identified by `i` contains an ample_panels instance.
   load_json: (i, response) ->
     @log "load(#{i}) json"
     panels_loaded = if @options.pages[i]['panel_selector'] then true else false
@@ -263,17 +302,20 @@
       @reloading = false
       @controls()

+  # Parse `response` from search results as json data.
   load_results: (response) ->
     @log "load_results()"
     i = @options.pages.length - 1

     if response.length > 0
+      # Build list-item for each item returned from search query.
       $.each response, (j,el) =>
         link = @build(el)
         li = $('

').append(link)
         $("#asset-results ul").amplePanels('append', li)
         @load_img(link, el.sizes.tn)
     else
+      # No results were returned, inject no-results verbiage.
       no_results = Mustache.to_html(@tpl('no_results'))
       @load_html(i, no_results)
       @loading.hide()
@@ -285,6 +327,7 @@
     @loading.hide()
     @controls()

+  # Builds each asset instance with proper attributes.
   build: (el) ->
     ref = this
     show_url = Mustache.to_html @options.show_url, { id: el.id }
@@ -296,13 +339,16 @@
       .addClass('draggable')
     link.addClass('document') if el.document == 'true'
     link.click ->
+      # Open a modal window on any asset instance's click event.
       ref.modal_open(el)
       false
     link

+  # Opens modal window instance for asset detail.
   modal_open: (data) ->
     @modal_active = true
     if data.document == 'true'
+      # Asset is a document, so lets instantiate PDFObject for viewing inline.
       html = Mustache.to_html(@tpl('pdf'),{ filename: data.uid, id: data.id })
       $.facebox("
#{html}
")
       myPDF = new PDFObject(
@@ -311,13 +357,16 @@
           view: "Fit"
       ).embed("pdf")
     else
+      # Asset is an image, lets display it inline, according to its orientation.
       geometry = if data.orientation == 'portrait' then 'x300>' else '480x>'
       url = "#{@options.base_url}#{@options.thumb_url}/#{geometry}?uid=#{data.uid}"
       delete_url = Mustache.to_html @options.show_url, { id: data.id }
       html = Mustache.to_html(@tpl('show'),{ filename: data.uid, src: url, orientation: data.orientation, id: data.id, delete_url: "#{@options.base_url}#{delete_url}" })
       $.facebox("
#{html}
")
+    # Update the asset timestamp.
     @touch(data)

+  # Create new image element from `src`, insert into `el` and fadeIn opacity.
   load_img: (el,src) ->
     img = new Image()
     $(img).load(->
@@ -326,16 +375,20 @@
       $(this).fadeIn()
     ).attr src: src

+  # Generates the next URL for paginated record sets.
   next_page_url: (i) ->
     @options.pages[i]['pages_loaded'] = 0 unless @options.pages[i]['pages_loaded']
     @options.pages[i]['pages_loaded'] += 1
     "#{@options.pages[i]['url']}?page=#{@options.pages[i]['pages_loaded']}"

+  # By touching asset records, we update the timestamp value which ensures our recently
+  # viewed tab contains accurate results. Called from `modal_open()`
   touch: (el) ->
     @log "touch()"
     touch_url = Mustache.to_html @options.touch_url, { id: el.id }
     $.post "#{@options.base_url}#{touch_url}"

+  # Instantiate an amplePanels instance within page `i` if `@options.pages[i]['panels']` is true.
   panels: (i) ->
     ref = this
     if @options.pages[i]['panels']
@@ -350,6 +403,7 @@
         .bind 'slide_horizontal', (e,d,dir) ->
           ref.load(i) if dir == 'next'

+  # Disable all panels, preventing any loading or key-driven actions from taking place within any amplePanels instance.
   disable_panels: ->
     @log "disable_panels()"
     ref = this
@@ -357,6 +411,8 @@
     $.each @options.pages, (i,el) ->
       $(ref.options.pages[i]['panel_selector']).amplePanels('disable') if ref.options.pages[i]['panel_selector']

+  # Enable panels instance contained with page identified by `i`.
+  # This allows key-events and previous/next actions to be executed.
   enable_panel: (i) ->
     @log "enable_panel(#{i})"
     if @options.pages[i]['panel_selector']
@@ -364,6 +420,7 @@
       $(@options.pages[i]['panel_selector']).amplePanels('enable')
       @controls()

+  # Toggles display of left/right arrows which control amplePanels paging event, determined by `display`.
   controls: (display=true) ->
     @log "controls(#{display})"
     display = false if $(@active_panel).find('li').length < @options.pages_options.per_page
@@ -373,29 +430,35 @@
       when false
         $('nav.controls').hide()

+  # Evaluates whether URL attached to page `i` has been loaded yet. Returns `boolean`.
   already_loaded: (i) ->
     typeof @options.pages[i]['loaded'] == 'boolean' && @options.pages[i]['loaded']

+  # Removes the asset from drop-target identified by `el`.
   remove: (el) ->
     parent = $(el).parent()
     parent.find('.droppable').empty().html('Drag Asset Here')
     parent.find('input').val('')
     $(el).hide()

+  # Called upon successful DELETE request for a specific asset. Removes any instances of
+  # asset identified by `id`, closes the modal window and reloads the first tab.
   delete: (id) ->
     @log "delete(#{id})"
-    console.log $("a#file-#{id}")
     $("a#file-#{id}").parent().remove()
     $(document).trigger('close.facebox')
     @reload(0)
     false

+  # Upon collapse, we disable panels.
   collapse: ->
     @disable_panels()

+  # Expands the asset toolbar and reenables the currently loaded tab.
   expand: ->
     @goto(@current)

+  # Setup all associated events.
   events: ->
     @modal_events()
     @global_events()
@@ -404,36 +467,37 @@
     @drag_events()
     @reload_events()
     @resize_events()
-    ref = this
+    @key_events()
+    @tab_events()
+    ref = this
+    # Reload the first tab following a successful upload.
+    $('body').bind 'ample_uploadify.complete', =>
+      @reload(0)
+    # Bind event to succesful deletion of an asset.
     $("a.asset-delete").live 'ajax:success', ->
       id = parseInt $(this).attr('data-id')
       ref.delete(id)
+    # Bind live event to any asset-remove element.
     $("a.asset-remove").live 'click', ->
       ref.remove(this)
       false
+    # Bind `toggle()` method to toolbar handle.
     $("##{@options.id}-handle").live 'click', =>
       @toggle()
       false
-    @key_down()
-    tabs = $("##{@options.id} a.tab")
-    ref = this
-    $.each tabs, (idx, el) ->
-      $(this).addClass('on') if idx == 0
-      $(el).click ->
-        ref.goto(idx)
-        false
-
+
+  # Bind events for global left/right arrows to currently active panel's `previous()` and `next()` methods.
   global_events: ->
     $('a.global.next').click =>
       $(@active_panel).amplePanels('next')
-
     $('a.global.previous').click =>
       $(@active_panel).amplePanels('previous')

+  # TODO: kill key events during drag?
   drag_events: ->
     @log "drag_events()"
-    # TODO: kill key events during drag?
-
+
+  # Open modal window when clicking an asset contained with a drop-target.
   drop_events: ->
     ref = this
     $('.asset-drop .droppable a').live 'click', ->
@@ -443,6 +507,7 @@
       , 'json'
       false

+  # Toggle the active state of key_events when user focuses / blurs on textareas or input fields.
   field_events: ->
     @log "field_events()"
     $('textarea, input').live 'blur', =>
@@ -450,12 +515,14 @@
     $('textarea, input').live 'focus', =>
       @keys_enabled = false

+  # Bind `reload()` method to assets-reload button.
   reload_events: ->
     @log "reload_events()"
     reload = $('')
     reload.appendTo('.asset-refresh').click (e) =>
       @reload(@current)

+  # Builds the markup for an asset dropped into a textarea.
   resize_events: ->
     $('.asset-resize').live 'click', =>
       constraints = $('#asset-constraints').val()
@@ -472,7 +539,8 @@
         html = ""
         $(@target_textarea).insertAtCaret (if $(@target_textarea).hasClass('textile') then textile else html)
         $(document).trigger('close.facebox')
-
+
+  # Toggles params when modal window is opened or closed.
   modal_events: ->
     @modal_active = false
     $(document).bind 'afterClose.facebox', =>
@@ -482,6 +550,8 @@
       @keys_enabled = false
       @modal_active = true

+  # Setup amplePanels instance for search results and bind search field to methods that
+  # execute request and parse response.
   search: ->
     @log 'search()'
     search_url = "#{@options.base_url}#{@options.search_url}"
@@ -501,7 +571,19 @@
         ref.load_results(response)
       , 'json'

-  key_down: ->
+  # Bind events to tabs.
+  tab_events: ->
+    tabs = $("##{@options.id} a.tab")
+    ref = this
+    $.each tabs, (idx, el) ->
+      $(this).addClass('on') if idx == 0
+      $(el).click ->
+        ref.goto(idx)
+        false
+
+  # Controls all user keyboard events. Binds as neccesary and
+  # prevents interaction when key functions are disabled.
+  key_events: ->
     ref = this
     previous = 37
     next = 39
@@ -509,6 +591,7 @@
     down = 40
     escape = 27

+    # Why does this need to be on keyup?
     $(document).keyup (e) =>
       return unless @keys_enabled
       switch e.keyCode
@@ -516,6 +599,7 @@
           @toggle() unless @modal_active
       e.stopPropagation();

+    # Keydown events.
     $(document).keydown (e) =>
       return unless @keys_enabled
       if @active_panel
@@ -530,10 +614,13 @@
             @next()
       e.stopPropagation();

+  # Returns Mustache template for template defined by `view`
   tpl: (view) ->
     @tpls()[view]

+  # Returns object containing all Mustache templates.
   tpls: ->
+    # Layout returns the HTML structure of the main asset toolbar.
     layout: '

@@ -559,12 +646,16 @@

'
+    # Handle returns HTML for the asset toolbar toggle handle.
     handle: '{{ title }}'
+    # Tab returns HTML for each tab instance.
     tab: '{{ title }}'
+    # Page returns generic HTML structure for each page.
     page: '

'
+    # Show represents the HTML used within the modal window detail view for non-document assets.
     show: '

@@ -573,14 +664,18 @@

{{ filename }}

       Delete

'
+    # PDF represents the HTML used within the modal window detail view for document assets.
     pdf: '

{{ filename }}

       Delete

'
+    # There's no content within this panels instance...
     empty: '
Oops. There\'s nothing here. You should upload something.
'
+    # Your search query returned an empty result set...
     no_results: '
Sorry. Your search returned zero results.
'
+    # Drop returns HTML used in the modal window resize view. This is used when dropping an asset onto a textarea.
     drop: '

@@ -605,11 +700,12 @@

'

+# Extend draggable to elements added to the DOM after page load.
 jQuery.fn.liveDraggable = (opts) ->
   @live "mouseover", ->
     $(this).data("init", true).draggable opts  unless $(this).data("init")

-
+# Insert `value` at the cursor position of the currently focused textarea or input field.
 jQuery.fn.insertAtCaret = (value) ->
   @each (i) ->
     if document.selection


Added correct footer controller

Added correct footer controller

--- app/assets/javascripts/controllers/common/footer_controller.coffee
+++ app/assets/javascripts/controllers/common/footer_controller.coffee
@@ -0,0 +1,7 @@
+angular.module('finalProject')
+.controller 'FooterController', ($scope) ->
+
+  init = () ->
+    $scope.test = "test"
+
+  init()


corrections

corrections

--- app/assets/javascripts/widgit/admin/plugins/color_editor.js.coffee
+++ app/assets/javascripts/widgit/admin/plugins/color_editor.js.coffee
@@ -39,8 +39,7 @@

       attributes       = $block.data 'attributes'
       previousColor    = attributes.color
-
-      @newColor         = $target.data('color-item')
+      @newColor        = $target.data('color-item')
       attributes.color = @newColor

       $block
@@ -48,7 +47,6 @@
         .addClass 'color-' + @newColor

       $modal.modal('hide')
-

       @update()

@@ -71,7 +69,6 @@

   makeColorList: ->
     colors = ["white", "blue", "green", "yellow", "red"]
-
     colorHtml = ''

     for index, color of colors


Update webgrabplus-siteini.cson

Update webgrabplus-siteini.cson

--- grammars/webgrabplus-siteini.cson
+++ grammars/webgrabplus-siteini.cson
@@ -1,4 +1,14 @@
-'scopeName': 'source.webgrabplus-siteini'
+{
+# url index elements
+'match': '(\\|)(urldate|channel|subpage|\'title\'|\'credits\'|\'productiondate\')(\\|)'
+'captures':
+  '1':
+    'name': 'entity.name.tag.siteini'
+  '2':
+    'name': 'entity.name.type.siteini'
+  '3':
+    'name': 'entity.name.tag.siteini'
+}'scopeName': 'source.webgrabplus-siteini'
 'name': 'WG++ siteini'
 'fileTypes': ['ini']
 'firstLineMatch': '^\\s*\\*[\\s*\\*]*WebGrab\\+Plus'
@@ -259,4 +269,15 @@
     '4':
       'name': 'entity.name.function.siteini'
 }
+{
+# url index elements
+'match': '(\\|)(urldate|channel|subpage|\'title\'|\'credits\'|\'productiondate\')(\\|)'
+'captures':
+  '1':
+    'name': 'entity.name.tag.siteini'
+  '2':
+    'name': 'entity.name.type.siteini'
+  '3':
+    'name': 'entity.name.tag.siteini'
+}
 ]


:lipstick:

:lipstick:

--- spec/app/tokenized-buffer-spec.coffee
+++ spec/app/tokenized-buffer-spec.coffee
@@ -76,7 +76,6 @@

     describe "when the buffer is fully tokenized", ->
       beforeEach ->
-        console.log "FULLY TOKENIZE"
         fullyTokenize(tokenizedBuffer)

       describe "when there is a buffer change that is smaller than the chunk size", ->


fixed async thens

fixed async thens

--- lib/mocha-given.coffee
+++ lib/mocha-given.coffee
@@ -69,7 +69,7 @@
 		i.apply @ for i in whenList if whenList.length
 		i.apply @ for i in invariantList if invariantList.length
 		o(fn).assert @, Array.prototype.slice.call arguments
-		done() if done
+		done() if not o(fn).hasArguments()

 MochaGivenSuite = (suite) ->
 	suites = [suite]


KodingAppsController: disable compileAppOnServer for now

--- client/Core/kodingappscontroller.coffee
+++ client/Core/kodingappscontroller.coffee
@@ -437,6 +437,8 @@

   @compileAppOnServer = (path, callback)->

+    return
+
     app = KodingAppsController.getAppInfoFromPath path, yes
     return  unless app


Terminal: sessionstackview converted to a KDView

--- client/Terminal/sessionstackview.coffee
+++ client/Terminal/sessionstackview.coffee
@@ -36,16 +36,6 @@
       warn err  unless err.code is "ErrNoSession"

-  pistachio: ->
-    {alias} = @getOptions()
-    """
-    {{> @loader }}
-    {{> @sessions }}
-    """
-
-
-  viewAppended: JView::viewAppended
-
   addSession: (session, index) ->

     {vm, delegate} = @getOptions()


minor

minor

--- client/app/MainApp/book/bookdata.coffee
+++ client/app/MainApp/book/bookdata.coffee
@@ -65,8 +65,8 @@
     embed     : "BookDevelopButton"
   ,
     title     : "Terminal"
-    content   : """
Terminal is a very important aspect of development, that's why we have invested a lot of time to provide a smooth, fast console.

-
Basically this is your virtual machine, that you're seeing its file of on your filetree. Whenever you signup we create this server for you. __CHANGE THIS COPY__
"""
+    content   : """
Terminal is a very important aspect of development, that's why we have invested a lot of time to provide a fast, smooth and responsive console.

+
__CHANGE THIS COPY__
"""
   ,
     title     : "Apps"
     content   : """
What makes Koding so useful are the apps provided by its users. Here you can perform one click installs of incredibly useful applications provided by users and major web development tools.


Wee code cleanup

Wee code cleanup

--- app/WebGLCanvas.coffee
+++ app/WebGLCanvas.coffee
@@ -21,7 +21,7 @@

 """

-VERTEX_INDEX_LOCATION = 0
+VERTEX_INDEX_ATTRIBUTE_LOCATION = 0

 # An object associated with a canvas element that manages the WebGL context
@@ -65,7 +65,7 @@

     @_createContext()

-    @_createGeometry()
+    @_updateGeometry()

     @_compileShader(@_vertexShader, DEFAULT_VSHADER_SOURCE)
     @_compileShader(@_fragmentShader, DEFAULT_FSHADER_SOURCE)
@@ -73,21 +73,14 @@

     @_linkProgram()

+    @_setData()
+
     @_render()

-  _render: ->
-
-
-
-    @gl.clearColor 0, 0, 0, 1
-    @gl.clear @gl.COLOR_BUFFER_BIT
-    @gl.drawArrays @gl.POINTS, 0, @vertexCount
-
-
-
-  ##
-  ## Scene construction functions that implement the resource management graph (see
-  ## diagram on class comment)
+
+
+  ##
+  ## Functions for each step in the resource management graph (see diagram on class comment)
   ##

   _createContext: ->
@@ -129,7 +122,7 @@
     gl.attachShader @_program, @_vertexShader
     gl.attachShader @_program, @_fragmentShader

-    gl.bindAttribLocation(@_program, VERTEX_INDEX_LOCATION, "a_VertexIndex")
+    gl.bindAttribLocation(@_program, VERTEX_INDEX_ATTRIBUTE_LOCATION, "a_VertexIndex")
     # Link the program object
     gl.linkProgram @_program
     # Check the result of linking
@@ -140,15 +133,11 @@
       error = gl.getProgramInfoLog(@_program)
       @trace.log 'Failed to link program: ' + error

-
-
-
-  _createGeometry: =>
+  _updateGeometry: ->

     gl = @gl

-    #gl.viewport 0, 0, width, height

     # Create vertex buffer
     vertices = new Float32Array(@vertexCount)
@@ -158,8 +147,34 @@
     gl.bindBuffer gl.ARRAY_BUFFER, @_vertexBuffer
     gl.bufferData gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW

-    gl.vertexAttribPointer VERTEX_INDEX_LOCATION, 1, gl.FLOAT, false, 0, 0
-    gl.enableVertexAttribArray VERTEX_INDEX_LOCATION
+    gl.vertexAttribPointer VERTEX_INDEX_ATTRIBUTE_LOCATION, 1, gl.FLOAT, false, 0, 0
+    gl.enableVertexAttribArray VERTEX_INDEX_ATTRIBUTE_LOCATION
+
+
+  _setData: ->
+
+
+
+  _render: ->
+
+
+    width = @canvas.offsetWidth * (window.devicePixelRatio || 1)
+    height = @canvas.offsetHeight * (window.devicePixelRatio || 1)
+
+    unless width is @_width and height is @_height
+
+      @_width = @canvas.width = width
+      @_height = @canvas.height = height
+
+      @gl.viewport 0, 0, width, height
+
+
+
+    @gl.clearColor 0, 0, 0, 1
+    @gl.clear @gl.COLOR_BUFFER_BIT
+    @gl.drawArrays @gl.POINTS, 0, @vertexCount
+
+


more cleanup

more cleanup

--- lib/phabricator.coffee
+++ lib/phabricator.coffee
@@ -514,183 +514,183 @@
     .then (body) ->
       id

-  changeColumns: (user, id, column, comment) ->
-    return new Promise (res, err) =>
-      @getBotPHID()
-      .bind({ botphid: null })
-      .bind({ columns: { } })
-      .then (botphid) =>
-        @botphid = botphid
-        query = { 'task_id': id }
-        @request(query, 'maniphest.info')
-      .then (body) =>
-        if not body.result.projectPHIDs? or body.result.projectPHIDs.length is 0
-          err 'This item has no tag/project yet.'
-        else
-          cols = Promise.map body.result.projectPHIDs, (phid) =>
-            @getProject(phid)
-            .then (projectData) ->
-              for i in Object.keys(projectData.data.columns)
-                if (new RegExp(column)).test i
-                  return { colname: i, colphid: projectData.data.columns[i] }
-          Promise.all cols
-      .then (cols) =>
-        cols = cols.filter (c) ->
-          c?
-        if cols.length > 0
-          query = {
-            'objectIdentifier': id,
-            'transactions[0][type]': 'subscribers.remove',
-            'transactions[0][value][0]': "#{@botphid}"
-            'transactions[1][type]': 'comment'
-          }
-          if comment?
-            query['transactions[1][value]'] = "#{comment} (#{user.name})"
-          else
-            query['transactions[1][value]'] = "moved by #{user.name}"
-          query['transactions[2][type]'] = 'column'
-          for c in cols
-            query['transactions[2][value][]'] = c.colphid
-          @request(query, 'maniphest.edit')
-          .then (body) ->
-            colnames = cols.map (c) ->
-              c.colname
-            res { id: id, columns: colnames.join(', ') }
-          .catch (e) ->
-            err e
-        else
-          err "The column '#{column}' does not exist."
-      .catch (e) ->
-        err e
-
-
-  changeTags: (user, id, alltags) ->
-    @getBotPHID()
-    .bind({ botphid: null })
-    .then (botphid) =>
-      @botphid = botphid
-      @getUser(user, user)
-    .then (userPhid) =>
-      query = { 'task_id': id }
-      @request(query, 'maniphest.info')
-    .then (body) =>
-      @makeTags(body.result.projectPHIDs, alltags)
-    .then (tags) =>
-      [ add, remove, messages ] = tags
-      query = {
-        'objectIdentifier': id,
-        'transactions[0][type]': 'subscribers.remove',
-        'transactions[0][value][0]': "#{@botphid}",
-        'transactions[1][type]': 'comment',
-        'transactions[1][value]': "tags changed by #{user.name}"
-      }
-      ind = 1
-      if add.length > 0
-        ind += 1
-        query["transactions[#{ind}][type]"] = 'projects.add'
-        x = add.map (t) -> t.phid
-        for p in x
-          query["transactions[#{ind}][value][]"] = p
-        messages.push "T#{id} added to #{add.map((t) -> t.tag).join(', ')}"
-      if remove.length > 0
-        ind += 1
-        query["transactions[#{ind}][type]"] = 'projects.remove'
-        x = remove.map (t) -> t.phid
-        for p in x
-          query["transactions[#{ind}][value][]"] = p
-        messages.push "T#{id} removed from #{remove.map((t) -> t.tag).join(', ')}"
-      if ind > 1
-        @request(query, 'maniphest.edit')
-          .then (body) ->
-            messages
-      else
-        [ 'No action needed.' ]
-
-  makeTags: (projs, alltags) ->
-    ins = alltags.trim().split('not in ')
-    tagin = ins.shift().split('in ').map (e) -> e.trim()
-    tagin.shift()
-    tagout = [ ]
-    for t in ins
-      els = t.split('in ')
-      tagout.push(els.shift().trim())
-      tagin = tagin.concat(els.map (e) -> e.trim())
-    msg = [ ]
-    add = Promise.map tagin, (tag) =>
-      @getProject(tag)
-      .then (projectData) ->
-        phid = projectData.data.phid
-        if phid not in projs
-          { tag: tag, phid: phid }
-        else
-          msg.push "already in #{tag}"
-          null
-    .filter (tag) ->
-      tag?
-    remove = Promise.map tagout, (tag) =>
-      @getProject(tag)
-      .then (projectData) ->
-        phid = projectData.data.phid
-        if phid in projs
-          { tag: tag, phid: phid }
-        else
-          msg.push "not in #{tag}"
-          null
-    .filter (tag) ->
-      tag?
-    return Promise.all([add, remove, msg])
-
-  updateStatus: (user, id, status, comment) ->
-    @getBotPHID()
-    .then (bot_phid) =>
-      query = {
-        'objectIdentifier': id,
-        'transactions[0][type]': 'status',
-        'transactions[0][value]': @statuses[status],
-        'transactions[1][type]': 'subscribers.remove',
-        'transactions[1][value][0]': "#{bot_phid}",
-        'transactions[2][type]': 'comment'
-      }
-      if comment?
-        query['transactions[2][value]'] = "#{comment} (#{user.name})"
-      else
-        query['transactions[2][value]'] = "status set to #{status} by #{user.name}"
-      @request(query, 'maniphest.edit')
-    .then (body) ->
-      id
-
-  updatePriority: (user, id, priority, comment) ->
-    @getBotPHID()
-    .then (bot_phid) =>
-      query = {
-        'objectIdentifier': id,
-        'transactions[0][type]': 'priority',
-        'transactions[0][value]': @priorities[priority],
-        'transactions[1][type]': 'subscribers.remove',
-        'transactions[1][value][0]': "#{bot_phid}",
-        'transactions[2][type]': 'comment'
-      }
-      if comment?
-        query['transactions[2][value]'] = "#{comment} (#{user.name})"
-      else
-        query['transactions[2][value]'] = "priority set to #{priority} by #{user.name}"
-      @request(query, 'maniphest.edit')
-    .then (body) ->
-      id
-
-  assignTask: (id, userphid) ->
-    @getBotPHID()
-    .then (bot_phid) =>
-      query = {
-        'objectIdentifier': "T#{id}",
-        'transactions[0][type]': 'owner',
-        'transactions[0][value]': "#{userphid}",
-        'transactions[1][type]': 'subscribers.remove',
-        'transactions[1][value][0]': "#{bot_phid}"
-      }
-      @request(query, 'maniphest.edit')
-    .then (body) ->
-      body.result.object.id
+  # changeColumns: (user, id, column, comment) ->
+  #   return new Promise (res, err) =>
+  #     @getBotPHID()
+  #     .bind({ botphid: null })
+  #     .bind({ columns: { } })
+  #     .then (botphid) =>
+  #       @botphid = botphid
+  #       query = { 'task_id': id }
+  #       @request(query, 'maniphest.info')
+  #     .then (body) =>
+  #       if not body.result.projectPHIDs? or body.result.projectPHIDs.length is 0
+  #         err 'This item has no tag/project yet.'
+  #       else
+  #         cols = Promise.map body.result.projectPHIDs, (phid) =>
+  #           @getProject(phid)
+  #           .then (projectData) ->
+  #             for i in Object.keys(projectData.data.columns)
+  #               if (new RegExp(column)).test i
+  #                 return { colname: i, colphid: projectData.data.columns[i] }
+  #         Promise.all cols
+  #     .then (cols) =>
+  #       cols = cols.filter (c) ->
+  #         c?
+  #       if cols.length > 0
+  #         query = {
+  #           'objectIdentifier': id,
+  #           'transactions[0][type]': 'subscribers.remove',
+  #           'transactions[0][value][0]': "#{@botphid}"
+  #           'transactions[1][type]': 'comment'
+  #         }
+  #         if comment?
+  #           query['transactions[1][value]'] = "#{comment} (#{user.name})"
+  #         else
+  #           query['transactions[1][value]'] = "moved by #{user.name}"
+  #         query['transactions[2][type]'] = 'column'
+  #         for c in cols
+  #           query['transactions[2][value][]'] = c.colphid
+  #         @request(query, 'maniphest.edit')
+  #         .then (body) ->
+  #           colnames = cols.map (c) ->
+  #             c.colname
+  #           res { id: id, columns: colnames.join(', ') }
+  #         .catch (e) ->
+  #           err e
+  #       else
+  #         err "The column '#{column}' does not exist."
+  #     .catch (e) ->
+  #       err e
+
+
+  # changeTags: (user, id, alltags) ->
+  #   @getBotPHID()
+  #   .bind({ botphid: null })
+  #   .then (botphid) =>
+  #     @botphid = botphid
+  #     @getUser(user, user)
+  #   .then (userPhid) =>
+  #     query = { 'task_id': id }
+  #     @request(query, 'maniphest.info')
+  #   .then (body) =>
+  #     @makeTags(body.result.projectPHIDs, alltags)
+  #   .then (tags) =>
+  #     [ add, remove, messages ] = tags
+  #     query = {
+  #       'objectIdentifier': id,
+  #       'transactions[0][type]': 'subscribers.remove',
+  #       'transactions[0][value][0]': "#{@botphid}",
+  #       'transactions[1][type]': 'comment',
+  #       'transactions[1][value]': "tags changed by #{user.name}"
+  #     }
+  #     ind = 1
+  #     if add.length > 0
+  #       ind += 1
+  #       query["transactions[#{ind}][type]"] = 'projects.add'
+  #       x = add.map (t) -> t.phid
+  #       for p in x
+  #         query["transactions[#{ind}][value][]"] = p
+  #       messages.push "T#{id} added to #{add.map((t) -> t.tag).join(', ')}"
+  #     if remove.length > 0
+  #       ind += 1
+  #       query["transactions[#{ind}][type]"] = 'projects.remove'
+  #       x = remove.map (t) -> t.phid
+  #       for p in x
+  #         query["transactions[#{ind}][value][]"] = p
+  #       messages.push "T#{id} removed from #{remove.map((t) -> t.tag).join(', ')}"
+  #     if ind > 1
+  #       @request(query, 'maniphest.edit')
+  #         .then (body) ->
+  #           messages
+  #     else
+  #       [ 'No action needed.' ]
+
+  # makeTags: (projs, alltags) ->
+  #   ins = alltags.trim().split('not in ')
+  #   tagin = ins.shift().split('in ').map (e) -> e.trim()
+  #   tagin.shift()
+  #   tagout = [ ]
+  #   for t in ins
+  #     els = t.split('in ')
+  #     tagout.push(els.shift().trim())
+  #     tagin = tagin.concat(els.map (e) -> e.trim())
+  #   msg = [ ]
+  #   add = Promise.map tagin, (tag) =>
+  #     @getProject(tag)
+  #     .then (projectData) ->
+  #       phid = projectData.data.phid
+  #       if phid not in projs
+  #         { tag: tag, phid: phid }
+  #       else
+  #         msg.push "already in #{tag}"
+  #         null
+  #   .filter (tag) ->
+  #     tag?
+  #   remove = Promise.map tagout, (tag) =>
+  #     @getProject(tag)
+  #     .then (projectData) ->
+  #       phid = projectData.data.phid
+  #       if phid in projs
+  #         { tag: tag, phid: phid }
+  #       else
+  #         msg.push "not in #{tag}"
+  #         null
+  #   .filter (tag) ->
+  #     tag?
+  #   return Promise.all([add, remove, msg])
+
+  # updateStatus: (user, id, status, comment) ->
+  #   @getBotPHID()
+  #   .then (bot_phid) =>
+  #     query = {
+  #       'objectIdentifier': id,
+  #       'transactions[0][type]': 'status',
+  #       'transactions[0][value]': @statuses[status],
+  #       'transactions[1][type]': 'subscribers.remove',
+  #       'transactions[1][value][0]': "#{bot_phid}",
+  #       'transactions[2][type]': 'comment'
+  #     }
+  #     if comment?
+  #       query['transactions[2][value]'] = "#{comment} (#{user.name})"
+  #     else
+  #       query['transactions[2][value]'] = "status set to #{status} by #{user.name}"
+  #     @request(query, 'maniphest.edit')
+  #   .then (body) ->
+  #     id
+
+  # updatePriority: (user, id, priority, comment) ->
+  #   @getBotPHID()
+  #   .then (bot_phid) =>
+  #     query = {
+  #       'objectIdentifier': id,
+  #       'transactions[0][type]': 'priority',
+  #       'transactions[0][value]': @priorities[priority],
+  #       'transactions[1][type]': 'subscribers.remove',
+  #       'transactions[1][value][0]': "#{bot_phid}",
+  #       'transactions[2][type]': 'comment'
+  #     }
+  #     if comment?
+  #       query['transactions[2][value]'] = "#{comment} (#{user.name})"
+  #     else
+  #       query['transactions[2][value]'] = "priority set to #{priority} by #{user.name}"
+  #     @request(query, 'maniphest.edit')
+  #   .then (body) ->
+  #     id
+
+  # assignTask: (id, userphid) ->
+  #   @getBotPHID()
+  #   .then (bot_phid) =>
+  #     query = {
+  #       'objectIdentifier': "T#{id}",
+  #       'transactions[0][type]': 'owner',
+  #       'transactions[0][value]': "#{userphid}",
+  #       'transactions[1][type]': 'subscribers.remove',
+  #       'transactions[1][value][0]': "#{bot_phid}"
+  #     }
+  #     @request(query, 'maniphest.edit')
+  #   .then (body) ->
+  #     body.result.object.id

   doActions: (user, id, commandString, comment) ->
     @getBotPHID()


Organisational changes

Organisational changes

Removed comments & moved code around.

--- lib/pinned-tabs.coffee
+++ lib/pinned-tabs.coffee
@@ -2,7 +2,6 @@
 {CompositeDisposable} = require 'atom'

 module.exports = PinnedTabs =
-    # Configuration of the package
     config:
         animation:
             title: 'Disable animations'
@@ -14,7 +13,7 @@
             description: 'Untick this for colored icons'
             default: false
             type: 'boolean'
-        closeUnpinned:
+        closeUnpinnedTabs:
             title: 'Disable the \'Close Unpinned Tabs\' option'
             description: 'Untick this to keep the option'
             default: true
@@ -25,12 +24,12 @@
             default: false
             type: 'boolean'

-    # Attribute used to store the workspace state.
     PinnedTabsState: undefined

+
+	# Core
     activate: (state) ->
         @setCommands()
-        @configObservers()
         @observers()

         # Recover the serialized session or start a new serializable state.
@@ -53,7 +52,7 @@
                 try
                     # Find the pane and tab-bar DOM objects for
                     # this pane.
-                    pane = panes.children[parseInt key, 10]
+                    pane = panes.children[parseInt(key, 10)]
                     tabbar = pane.querySelector '.tab-bar'

                     # Pin the first N tabs, since pinned tabs are
@@ -70,16 +69,14 @@
     serialize: ->
         @PinnedTabsState.serialize()

-
-    # Register commands for this package.
     setCommands: ->
         @subscriptions = new CompositeDisposable
         @subscriptions.add atom.commands.add 'atom-workspace', 'pinned-tabs:pin': => @pinActive()
         @subscriptions.add atom.commands.add 'atom-workspace', 'pinned-tabs:pin-selected': => @pinSelected()
-        @subscriptions.add atom.commands.add 'atom-workspace', 'pinned-tabs:close-unpinned': => @closeUnpinned()
+        @subscriptions.add atom.commands.add 'atom-workspace', 'pinned-tabs:close-unpinned': => @closeUnpinnedTabs()

-    # Add an event listener for when the value of the settings are changed.
-    configObservers: ->
+    observers: ->
+        # Config observers
         body = document.querySelector 'body'
         atom.config.observe 'pinned-tabs.animation', (newValue) ->
             if newValue
@@ -91,7 +88,7 @@
                 body.classList.add 'pinned-icons-colorless'
             else
                 body.classList.remove 'pinned-icons-colorless'
-        atom.config.observe 'pinned-tabs.closeUnpinned', (newValue) =>
+        atom.config.observe 'pinned-tabs.closeUnpinnedTabs', (newValue) =>
             body = document.querySelector 'body'
             if newValue
                 body.classList.remove 'close-unpinned'
@@ -103,8 +100,7 @@
             else
                 body.classList.add 'pinned-tabs-enable-modified'

-    # Observer panes
-    observers: ->
+        # General observers
         atom.workspace.onDidAddPaneItem (event) =>
             setTimeout (=>
                 # Get information about the tab
@@ -130,72 +126,62 @@
             catch error
                 return

+    closeUnpinnedTabs: ->
+        activePane = document.querySelector '.pane.active'
+        tabbar = activePane.querySelector '.tab-bar'

-    # Method to pin the active tab.
+        activePane = atom.workspace.getActivePane()
+        tabs = tabbar.querySelectorAll '.tab'
+        for i in [(tabs.length - 1)..0]
+            if !tabs[i].classList.contains('pinned')
+                activePane.itemAtIndex i
+                activePane.destroyItem activePane.itemAtIndex(i)
+
+
+	# Pin tabs
     pinActive: ->
         @pin document.querySelector('.tab-bar .tab.active')

-    # Method to pin the selected (via contextmenu) tab.
     pinSelected: ->
         @pin atom.contextMenu.activeElement

-    # Method that pins/unpins a tab given its element.
     pin: (e) ->
-        # Get information about the tab
-        try
-            tab = @getTabInformation e
-        catch error
-            return
+        return unless tab = @getTabInformation e

-        # Calculate the new index for this tab based
-        # on the amount of pinned tabs within this pane.
         if tab.isPinned
-            # If the element has the element 'pinned', it
-            # is currently being unpinned. So the new index
-            # is one off when look at the amount of pinned
-            # tabs, because it actually includes the tab
-            # that is being unpinned.
-            tab.pinIndex -= 1
-
-            # Removed one pinned tab from the state key for this pane.
             @PinnedTabsState.data[tab.paneIndex] -= 1
+            tab.pane.moveItem(tab.item, tab.unpinIndex)
         else
-            # Initialize the state kye for this pane if needed.
+            # Initialize the state key for this pane if needed.
             @PinnedTabsState.data[tab.paneIndex] = 0 if @PinnedTabsState.data[tab.paneIndex] == undefined

-            # Add one pinned tab from the state key for this pane.
             @PinnedTabsState.data[tab.paneIndex] += 1
+            tab.pane.moveItem(tab.item, tab.pinIndex)

-        # Move the tab to its new index
-        tab.pane.moveItem(tab.item, tab.pinIndex)
-
-        # Finally, toggle the 'pinned' class on the tab after a
-        # timout of 1 millisecond. This will ensure the animation
-        # of pinning the tab will run.
-        callback = -> e.classList.toggle 'pinned'
-        setTimeout callback, 1
+        setTimeout (->
+            e.classList.toggle 'pinned'
+        ), 1

-    # Get information about a tab
+    # Utility
     getTabInformation: (e) ->
-        # Get related nodes
-        tabbar = e.parentNode
-        paneNode = tabbar.parentNode
-        axis = paneNode.parentNode
+        tabbarNode = e.parentNode
+        paneNode = tabbarNode.parentNode
+        axisNode = paneNode.parentNode

-        # Get the index values of relevant elements
-        curIndex = Array.prototype.indexOf.call(tabbar.children, e)
-        paneIndex = Array.prototype.indexOf.call(axis.children, paneNode)
+        tabIndex = Array.prototype.indexOf.call(tabbarNode.children, e)
+        paneIndex = Array.prototype.indexOf.call(axisNode.children, paneNode)
         pinIndex = paneNode.querySelectorAll('.pinned').length

-        # Get the related pane & texteditor
         pane = atom.workspace.getPanes()[paneIndex / 2]
-        item = pane.itemAtIndex curIndex
+        item = pane.itemAtIndex(tabIndex)

         return {
-            curIndex: curIndex,
+            tabIndex: tabIndex,
+            paneIndex: paneIndex,
+
             pinIndex: pinIndex,
-            paneIndex: paneIndex,
+            unpinIndex: pinIndex - 1,

             itemNode: undefined,
             paneNode: undefined,
@@ -205,16 +191,3 @@

             isPinned: e.classList.contains 'pinned'
         }
-
-
-    # Close all unpinned tabs
-    closeUnpinned: ->
-        activePane = document.querySelector '.pane.active'
-        tabbar = activePane.querySelector '.tab-bar'
-
-        activePane = atom.workspace.getActivePane()
-        tabs = tabbar.querySelectorAll '.tab'
-        for i in [(tabs.length - 1)..0]
-            if !tabs[i].classList.contains('pinned')
-                activePane.itemAtIndex i
-                activePane.destroyItem activePane.itemAtIndex(i)


add missing file

add missing file

--- common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee
+++ common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee
@@ -306,7 +306,7 @@
     else if @child_state == 'initial'
       @answer_area.attr("disabled", false)
       @submit_button.prop('value', gettext 'Submit')
-      @submit_button.click @confirm_save_answer
+      @submit_button.click @check_is_answer_empty
       @setup_file_upload()
       @save_button.click @store_answer
       @save_button.show()
@@ -395,6 +395,16 @@
       @answer_area.attr("disabled", false)
       @gentle_alert response.error

+  check_is_answer_empty: (event) =>
+    if @can_upload_files == false and @answer_area.val() == ""
+      @abandon_empty_answer()
+      ###
+      Also the user can try to submit an empty answer without file in case @can_upload_files == true.
+      This alternative is processed in openendedchild.py.
+      ###
+    else
+      @confirm_save_answer(event)
+
   confirm_save_answer: (event) =>
     ###
     Translators: This string appears in a confirmation box after one tries to submit
@@ -403,6 +413,13 @@
     confirmation_text = gettext 'Please confirm that you wish to submit your work. You will not be able to make any changes after submitting.'
     accessible_confirm confirmation_text, =>
       @save_answer(event)
+
+  abandon_empty_answer: (event) =>
+    ###
+    Translators: This string appears when one's trying to submit an empty answer
+    ###
+    abandonment_text = gettext "You're trying to submit an empty answer. Please type an answer in the corresponding field and then submit."
+    @gentle_alert abandonment_text

   save_answer: (event) =>
     @$el.find(@oe_alert_sel).remove()


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/flickerable.coffee
+++ test/flickerable.coffee
@@ -16,7 +16,8 @@

   player.include Flickerable

-
+  player.flicker
+    du

 test 'it should change the alpha value when the flicker duration has elapsed', ->
   player = GameObject


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/game_object.coffee
+++ test/game_object.coffee
@@ -33,7 +33,8 @@

   equals o.closest([other, other2]), other

-test "#"
+test "#sendOrApply", ->
+

 test "[event] create", 2, ->
   GameObject


sugar for file#unzip

sugar for file#unzip

--- src/models/File.coffee
+++ src/models/File.coffee
@@ -36,9 +36,14 @@
   #     failureCallbacks: [callbacks.onFailure]

   unzip: (options={}, callbacks={})->
+    destinationPath = if options.constructor.name == "String"
+      options
+    else
+      options.destinationPath
+
     parameters =
       filenameWithPath: @path
-      path: options.destinationPath
+      path: destinationPath

     steroids.nativeBridge.nativeCall
       method: "unzip"


lodchart: cleanup test_lodchart; in prev commit, added mouseover for chr rect

--- lodchart/test_lodchart.coffee
+++ lodchart/test_lodchart.coffee
@@ -58,8 +58,4 @@

   chart2.datum(data)
     .call(mychart_hk)
-
-  # animate points at markerson click
-  mychart_em.markerSelect()
-            .on("click", (d) ->


append, and suppress activity start/stop in kiosk log processor

--- logtools/tabletget2tsv.coffee
+++ logtools/tabletget2tsv.coffee
@@ -29,7 +29,8 @@
   systime = entry.time
   datetime = new Date(systime).toString()
   output = entry.time+"\t"+datetime+"\t"+entry.component+"\t"+entry.event
-  if entry.event=='view.attract.hide' or entry.event=='view.attract.show' or entry.event=='activity.pause' or entry.event=='activity.resume'
+  if entry.event=='view.attract.hide' or entry.event=='view.attract.show'
+    # or entry.event=='activity.pause' or entry.event=='activity.resume'
     outputs.push output
   else if entry.event=='user.selectEntry'
     outputs.push output+"\t"+entry.info.id+"\t"+entry.info.title
@@ -89,7 +90,7 @@

 console.log "Write to #{outfn}..."
 try
-  out = fs.openSync outfn, "w+"
+  out = fs.openSync outfn, "a"
   for output in outputs
     fs.writeSync out,output
     fs.writeSync out,"\n"


Update muttrc Atom file type configuration.

--- home/.atom/config.cson
+++ home/.atom/config.cson
@@ -67,7 +67,7 @@
     "^.htoprc": "text.generic-config"
     "^.inputrc": "text.generic-config"
     "^.mailcap": "source.shell"
-    "^.mutt*": "source.shell"
+    "^muttrc": "source.shell"
     "^.profile$": "source.shell"
     "^.psqlrc": "source.sql"
     "^.rspec$": "text.generic-config"


atom config

atom config

--- home/.atom/config.cson
+++ home/.atom/config.cson
@@ -3,6 +3,13 @@
     userId: "32038c2f-23f4-5169-bb02-fd41cb60e8ec"
   welcome:
     showOnStartup: false
-  core: {}
+  core:
+    audioBeep: false
   editor:
     invisibles: {}
+    fontSize: 14
+    showInvisibles: true
+  minimap: {}
+  linter: {}
+  "tree-view":
+    showOnRightSide: true


Updated settings.

Updated settings.

--- home/.atom/config.cson
+++ home/.atom/config.cson
@@ -8,7 +8,7 @@
   'metrics':
     'userId': 'f98723003432ede403e38c56f7fee9ad398c422e'
   'editor':
-    'fontSize': 12
+    'fontSize': 13
     'showInvisibles': true
   'core':
     'themes': [
@@ -37,3 +37,8 @@
   'highlight-line':
     'enableUnderline': true
   'autoclose-html': {}
+  'linter': {}
+'.ini.source':
+  'editor': {}
+'.plain.text':
+  'editor': {}