From 25e4d8c3657dd83258b65ad018b867557722a38c Mon Sep 17 00:00:00 2001
From: Steffen van Bergerem <svbergerem@online.de>
Date: Mon, 5 Oct 2015 22:07:57 +0200
Subject: [PATCH] Fix shortcuts after changing streams

---
 app/assets/javascripts/app/router.js          |  1 +
 .../javascripts/app/views/stream/shortcuts.js | 35 +++++++-----------
 .../javascripts/app/views/stream_view.js      |  8 ++---
 features/desktop/keyboard_navigation.feature  | 13 +++++++
 .../app/views/stream/shortcuts_spec.js        | 36 +++----------------
 5 files changed, 32 insertions(+), 61 deletions(-)

diff --git a/app/assets/javascripts/app/router.js b/app/assets/javascripts/app/router.js
index e95e520e4e..43befff7a5 100644
--- a/app/assets/javascripts/app/router.js
+++ b/app/assets/javascripts/app/router.js
@@ -92,6 +92,7 @@ app.Router = Backbone.Router.extend({
     app.stream.fetch();
     app.page = new app.views.Stream({model : app.stream});
     app.publisher = app.publisher || new app.views.Publisher({collection : app.stream.items});
+    app.shortcuts = app.shortcuts || new app.views.StreamShortcuts({el: $(document)});
 
     var streamFacesView = new app.views.StreamFaces({collection : app.stream.items});
 
diff --git a/app/assets/javascripts/app/views/stream/shortcuts.js b/app/assets/javascripts/app/views/stream/shortcuts.js
index 70c473b7ee..b09c6e753b 100644
--- a/app/assets/javascripts/app/views/stream/shortcuts.js
+++ b/app/assets/javascripts/app/views/stream/shortcuts.js
@@ -1,21 +1,11 @@
 // @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later
 
-app.views.StreamShortcuts = {
-
+app.views.StreamShortcuts = Backbone.View.extend({
   _headerSize: 50,
 
-
-  setupShortcuts : function() {
-    $(document).on('keydown', _.bind(this._onHotkeyDown, this));
-    $(document).on('keyup', _.bind(this._onHotkeyUp, this));
-
-    this.on('hotkey:gotoNext', this.gotoNext, this);
-    this.on('hotkey:gotoPrev', this.gotoPrev, this);
-    this.on('hotkey:likeSelected', this.likeSelected, this);
-    this.on('hotkey:commentSelected', this.commentSelected, this);
-    this.on('hotkey:reshareSelected', this.reshareSelected, this);
-    this.on('hotkey:expandSelected', this.expandSelected, this);
-    this.on('hotkey:openFirstLinkSelected', this.openFirstLinkSelected, this);
+  events: {
+    "keydown": "_onHotkeyDown",
+    "keyup": "_onHotkeyUp"
   },
 
   _onHotkeyDown: function(event) {
@@ -28,10 +18,10 @@ app.views.StreamShortcuts = {
     // trigger the events based on what key was pressed
     switch (String.fromCharCode( event.which ).toLowerCase()) {
       case "j":
-        this.trigger('hotkey:gotoNext');
+        this.gotoNext();
         break;
       case "k":
-        this.trigger('hotkey:gotoPrev');
+        this.gotoPrev();
         break;
       default:
     }
@@ -47,19 +37,19 @@ app.views.StreamShortcuts = {
     // trigger the events based on what key was pressed
     switch (String.fromCharCode( event.which ).toLowerCase()) {
       case "c":
-        this.trigger('hotkey:commentSelected');
+        this.commentSelected();
         break;
       case "l":
-        this.trigger('hotkey:likeSelected');
+        this.likeSelected();
         break;
       case "r":
-        this.trigger('hotkey:reshareSelected');
+        this.reshareSelected();
         break;
       case "m":
-        this.trigger('hotkey:expandSelected');
+        this.expandSelected();
         break;
       case "o":
-        this.trigger('hotkey:openFirstLinkSelected');
+        this.openFirstLinkSelected();
         break;
       default:
     }
@@ -132,6 +122,5 @@ app.views.StreamShortcuts = {
     //add the selection and selected-class to new post
     element.className+=" shortcut_selected highlighted";
   },
-};
+});
 // @license-end
-
diff --git a/app/assets/javascripts/app/views/stream_view.js b/app/assets/javascripts/app/views/stream_view.js
index 9d5d036ca7..d9ed053063 100644
--- a/app/assets/javascripts/app/views/stream_view.js
+++ b/app/assets/javascripts/app/views/stream_view.js
@@ -1,10 +1,7 @@
 // @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later
 
-//= require ./stream/shortcuts
+app.views.Stream = app.views.InfScroll.extend({
 
-app.views.Stream = app.views.InfScroll.extend(_.extend(
-  app.views.StreamShortcuts, {
-  	
   initialize: function() {
     this.stream = this.model;
     this.collection = this.stream.items;
@@ -14,7 +11,6 @@ app.views.Stream = app.views.InfScroll.extend(_.extend(
     this.setupNSFW();
     this.setupLightbox();
     this.setupInfiniteScroll();
-    this.setupShortcuts();
     this.markNavSelected();
   },
 
@@ -38,5 +34,5 @@ app.views.Stream = app.views.InfScroll.extend(_.extend(
     streamSelection.find("[data-stream]").removeClass("selected");
     streamSelection.find("[data-stream='" + activeStream + "']").addClass("selected");
   }
-}));
+});
 // @license-end
diff --git a/features/desktop/keyboard_navigation.feature b/features/desktop/keyboard_navigation.feature
index 228b4ca055..99e286e0fb 100644
--- a/features/desktop/keyboard_navigation.feature
+++ b/features/desktop/keyboard_navigation.feature
@@ -22,6 +22,19 @@ Feature: Keyboard navigation
     Then post 2 should be highlighted
     And I close the publisher
 
+  Scenario: navigate downwards after changing the stream
+    When I go to the activity stream page
+    And I click on selector "[data-stream='stream'] a"
+    Then I should see "Stream" within ".stream_title"
+
+    When I press the "J" key somewhere
+    Then post 1 should be highlighted
+    And I should have navigated to the highlighted post
+
+    When I press the "J" key somewhere
+    Then post 2 should be highlighted
+    And I should have navigated to the highlighted post
+
   Scenario: navigate upwards
     When I scroll to post 3
     And I press the "K" key somewhere
diff --git a/spec/javascripts/app/views/stream/shortcuts_spec.js b/spec/javascripts/app/views/stream/shortcuts_spec.js
index 6ce7e05fd1..a90b8ddd5a 100644
--- a/spec/javascripts/app/views/stream/shortcuts_spec.js
+++ b/spec/javascripts/app/views/stream/shortcuts_spec.js
@@ -6,25 +6,16 @@ describe("app.views.StreamShortcuts", function () {
 
     this.stream = new app.models.Stream();
     this.stream.add([this.post1, this.post2]);
-    this.view = new app.views.Stream({model : this.stream});
+    this.streamView = new app.views.Stream({model : this.stream});
+    spec.content().html(this.streamView.render().el);
+    this.view = new app.views.StreamShortcuts({el: $(document)});
 
-    this.view.render();
-    expect(this.view.$('div.stream_element.loaded').length).toBe(2);
-  });
-
-  describe("loading the stream", function(){
-    it("should setup the shortcuts", function(){
-      spyOn(this.view, 'setupShortcuts');
-      this.view.initialize();
-      expect(this.view.setupShortcuts).toHaveBeenCalled();
-    });
+    expect(spec.content().find("div.stream_element.loaded").length).toBe(2);
   });
 
   describe("pressing 'j'", function(){
-
     it("should call 'gotoNext' if not pressed in an input field", function(){
       spyOn(this.view, 'gotoNext');
-      this.view.initialize();
       var e = $.Event("keydown", { which: 74, target: {type: "div"} });
       //verify that the test is correct
       expect(String.fromCharCode( e.which ).toLowerCase()).toBe('j');
@@ -41,7 +32,6 @@ describe("app.views.StreamShortcuts", function () {
     it("shouldn't do anything if the user types in an input field", function(){
       spyOn(this.view, 'gotoNext');
       spyOn(this.view, 'selectPost');
-      this.view.initialize();
       var e = $.Event("keydown", { which: 74, target: {type: "textarea"} });
       //verify that the test is correct
       expect(String.fromCharCode( e.which ).toLowerCase()).toBe('j');
@@ -52,10 +42,8 @@ describe("app.views.StreamShortcuts", function () {
   });
 
   describe("pressing 'k'", function(){
-
     it("should call 'gotoPrev' if not pressed in an input field", function(){
       spyOn(this.view, 'gotoPrev');
-      this.view.initialize();
       var e = $.Event("keydown", { which: 75, target: {type: "div"} });
       //verify that the test is correct
       expect(String.fromCharCode( e.which ).toLowerCase()).toBe('k');
@@ -72,7 +60,6 @@ describe("app.views.StreamShortcuts", function () {
     it("shouldn't do anything if the user types in an input field", function(){
       spyOn(this.view, 'gotoPrev');
       spyOn(this.view, 'selectPost');
-      this.view.initialize();
       var e = $.Event("keydown", { which: 75, target: {type: "textarea"} });
       //verify that the test is correct
       expect(String.fromCharCode( e.which ).toLowerCase()).toBe('k');
@@ -83,10 +70,8 @@ describe("app.views.StreamShortcuts", function () {
   });
 
   describe("pressing 'c'", function(){
-
     it("should click on the comment-button if not pressed in an input field", function(){
       spyOn(this.view, 'commentSelected');
-      this.view.initialize();
       var e = $.Event("keyup", { which: 67, target: {type: "div"} });
       //verify that the test is correct
       expect(String.fromCharCode( e.which ).toLowerCase()).toBe('c');
@@ -96,7 +81,6 @@ describe("app.views.StreamShortcuts", function () {
 
     it("shouldn't do anything if the user types in an input field", function(){
       spyOn(this.view, 'commentSelected');
-      this.view.initialize();
       var e = $.Event("keyup", { which: 67, target: {type: "textarea"} });
       //verify that the test is correct
       expect(String.fromCharCode( e.which ).toLowerCase()).toBe('c');
@@ -106,10 +90,8 @@ describe("app.views.StreamShortcuts", function () {
   });
 
   describe("pressing 'l'", function(){
-
     it("should click on the like-button if not pressed in an input field", function(){
       spyOn(this.view, 'likeSelected');
-      this.view.initialize();
       var e = $.Event("keyup", { which: 76, target: {type: "div"} });
       //verify that the test is correct
       expect(String.fromCharCode( e.which ).toLowerCase()).toBe('l');
@@ -119,7 +101,6 @@ describe("app.views.StreamShortcuts", function () {
 
     it("shouldn't do anything if the user types in an input field", function(){
       spyOn(this.view, 'likeSelected');
-      this.view.initialize();
       var e = $.Event("keyup", { which: 76, target: {type: "textarea"} });
       //verify that the test is correct
       expect(String.fromCharCode( e.which ).toLowerCase()).toBe('l');
@@ -129,10 +110,8 @@ describe("app.views.StreamShortcuts", function () {
   });
 
   describe("pressing 'r'", function(){
-
     it("should click on the reshare-button if not pressed in an input field", function(){
       spyOn(this.view, 'reshareSelected');
-      this.view.initialize();
       var e = $.Event("keyup", { which: 82, target: {type: "div"} });
       //verify that the test is correct
       expect(String.fromCharCode( e.which ).toLowerCase()).toBe('r');
@@ -142,7 +121,6 @@ describe("app.views.StreamShortcuts", function () {
 
     it("shouldn't do anything if the user types in an input field", function(){
       spyOn(this.view, 'reshareSelected');
-      this.view.initialize();
       var e = $.Event("keyup", { which: 82, target: {type: "textarea"} });
       //verify that the test is correct
       expect(String.fromCharCode( e.which ).toLowerCase()).toBe('r');
@@ -152,10 +130,8 @@ describe("app.views.StreamShortcuts", function () {
   });
 
   describe("pressing 'm'", function(){
-
     it("should click on the more-button if not pressed in an input field", function(){
       spyOn(this.view, 'expandSelected');
-      this.view.initialize();
       var e = $.Event("keyup", { which: 77, target: {type: "div"} });
       //verify that the test is correct
       expect(String.fromCharCode( e.which ).toLowerCase()).toBe('m');
@@ -165,7 +141,6 @@ describe("app.views.StreamShortcuts", function () {
 
     it("shouldn't do anything if the user types in an input field", function(){
       spyOn(this.view, 'expandSelected');
-      this.view.initialize();
       var e = $.Event("keyup", { which: 77, target: {type: "textarea"} });
       //verify that the test is correct
       expect(String.fromCharCode( e.which ).toLowerCase()).toBe('m');
@@ -175,10 +150,8 @@ describe("app.views.StreamShortcuts", function () {
   });
 
   describe("pressing 'o'", function(){
-
     it("should click on the more-button if not pressed in an input field", function(){
       spyOn(this.view, 'openFirstLinkSelected');
-      this.view.initialize();
       var e = $.Event("keyup", { which: 79, target: {type: "div"} });
       //verify that the test is correct
       expect(String.fromCharCode( e.which ).toLowerCase()).toBe('o');
@@ -188,7 +161,6 @@ describe("app.views.StreamShortcuts", function () {
 
     it("shouldn't do anything if the user types in an input field", function(){
       spyOn(this.view, 'openFirstLinkSelected');
-      this.view.initialize();
       var e = $.Event("keyup", { which: 79, target: {type: "textarea"} });
       //verify that the test is correct
       expect(String.fromCharCode( e.which ).toLowerCase()).toBe('o');
-- 
GitLab