Unverified Commit 35aa0bad authored by Steffen van Bergerem's avatar Steffen van Bergerem Committed by Dennis Schubert
Browse files

Refactor stream shortcuts

closes #7127
parent 0a264c1f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@ Note: Although this is a minor release, the configuration file changed because t
* Refactored post interactions on the single post view [#7089](https://github.com/diaspora/diaspora/pull/7089)
* Extract inline JavaScript [#7113](https://github.com/diaspora/diaspora/pull/7113)
* Port conversations inbox to backbone.js [#7108](https://github.com/diaspora/diaspora/pull/7108)
* Refactored stream shortcuts for more flexibility [#7127](https://github.com/diaspora/diaspora/pull/7127)

## Bug fixes
* Post comments no longer get collapsed when interacting with a post [#7040](https://github.com/diaspora/diaspora/pull/7040)
+31 −0
Original line number Diff line number Diff line
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later
(function() {
  app.helpers.Shortcuts = function(evtname, fn) {
    var textAcceptingInputTypes = [
      "color",
      "date",
      "datetime",
      "datetime-local",
      "email",
      "month",
      "number",
      "password",
      "range",
      "search",
      "select",
      "text",
      "textarea",
      "time",
      "url",
      "week"
    ];

    $("body").on(evtname, function(event) {
      // make sure that the user is not typing in an input field
      if (textAcceptingInputTypes.indexOf(event.target.type) === -1) {
        fn(event);
      }
    });
  };
})();
// @license-end
+3 −15
Original line number Diff line number Diff line
@@ -3,18 +3,12 @@
app.views.StreamShortcuts = Backbone.View.extend({
  _headerSize: 60,

  events: {
    "keydown": "_onHotkeyDown",
    "keyup": "_onHotkeyUp"
  initialize: function() {
    app.helpers.Shortcuts("keydown", this._onHotkeyDown.bind(this));
    app.helpers.Shortcuts("keyup", this._onHotkeyUp.bind(this));
  },

  _onHotkeyDown: function(event) {
    //make sure that the user is not typing in an input field
    var textAcceptingInputTypes = ["textarea", "select", "text", "password", "number", "email", "url", "range", "date", "month", "week", "time", "datetime", "datetime-local", "search", "color"];
    if(jQuery.inArray(event.target.type, textAcceptingInputTypes) > -1){
      return;
    }

    // trigger the events based on what key was pressed
    switch (String.fromCharCode( event.which ).toLowerCase()) {
      case "j":
@@ -28,12 +22,6 @@ app.views.StreamShortcuts = Backbone.View.extend({
  },

  _onHotkeyUp: function(event) {
    //make sure that the user is not typing in an input field
    var textAcceptingInputTypes = ["textarea", "select", "text", "password", "number", "email", "url", "range", "date", "month", "week", "time", "datetime", "datetime-local", "search", "color"];
    if(jQuery.inArray(event.target.type, textAcceptingInputTypes) > -1){
      return;
    }

    // trigger the events based on what key was pressed
    switch (String.fromCharCode( event.which ).toLowerCase()) {
      case "c":
+17 −0
Original line number Diff line number Diff line
describe("app.helpers.Shortcuts", function() {
  it("calls the function when the event has been fired outside of an input field", function() {
    var spy = jasmine.createSpy();
    spec.content().append("<div class='hotkey-div'></div>");
    app.helpers.Shortcuts("keydown", spy);
    $(".hotkey-div").trigger("keydown");
    expect(spy).toHaveBeenCalled();
  });

  it("doesn't call the function when the event has been fired in an input field", function() {
    var spy = jasmine.createSpy();
    spec.content().append("<textarea class='hotkey-textarea'></textarea>");
    app.helpers.Shortcuts("keydown", spy);
    $(".hotkey-textarea").trigger("keydown");
    expect(spy).not.toHaveBeenCalled();
  });
});
+58 −94
Original line number Diff line number Diff line
@@ -13,131 +13,95 @@ describe("app.views.StreamShortcuts", function () {
    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');
  describe("initialize", function() {
    it("setups the shortcuts", function() {
      spyOn(app.helpers, "Shortcuts").and.callThrough();
      spyOn(app.views.StreamShortcuts.prototype, "_onHotkeyDown");
      spyOn(app.views.StreamShortcuts.prototype, "_onHotkeyUp");
      this.view = new app.views.StreamShortcuts({el: $(document)});
      expect(app.helpers.Shortcuts.calls.count()).toBe(2);

      $("body").trigger($.Event("keydown", {which: Keycodes.J, target: {type: "textarea"}}));
      $("body").trigger($.Event("keyup", {which: Keycodes.J, target: {type: "textarea"}}));
      expect(app.views.StreamShortcuts.prototype._onHotkeyDown).not.toHaveBeenCalled();
      expect(app.views.StreamShortcuts.prototype._onHotkeyUp).not.toHaveBeenCalled();

      var e = $.Event("keydown", {which: Keycodes.J, target: {type: "div"}});
      this.view._onHotkeyDown(e);
      expect(this.view.gotoNext).toHaveBeenCalled();
    });
      $("body").trigger(e);
      expect(app.views.StreamShortcuts.prototype._onHotkeyDown).toHaveBeenCalledWith(e);

    it("'gotoNext' should call 'selectPost'", function(){
      spyOn(this.view, 'selectPost');
      this.view.gotoNext();
      expect(this.view.selectPost).toHaveBeenCalled();
      e = $.Event("keyup", {which: Keycodes.J, target: {type: "div"}});
      $("body").trigger(e);
      expect(app.views.StreamShortcuts.prototype._onHotkeyUp).toHaveBeenCalledWith(e);
    });
  });

    it("shouldn't do anything if the user types in an input field", function(){
      spyOn(this.view, 'gotoNext');
      spyOn(this.view, 'selectPost');
      var e = $.Event("keydown", { which: Keycodes.J, target: {type: "textarea"} });
  describe("_onHotkeyDown", function() {
    it("calls goToNext when the user pressed 'J'", function() {
      spyOn(this.view, "gotoNext");
      var e = $.Event("keydown", {which: Keycodes.J, target: {type: "div"}});
      this.view._onHotkeyDown(e);
      expect(this.view.gotoNext).not.toHaveBeenCalled();
      expect(this.view.selectPost).not.toHaveBeenCalled();
    });
      expect(this.view.gotoNext).toHaveBeenCalled();
    });

  describe("pressing 'k'", function(){
    it("should call 'gotoPrev' if not pressed in an input field", function(){
      spyOn(this.view, 'gotoPrev');
    it("calls gotoPrev when the user pressed 'K'", function() {
      spyOn(this.view, "gotoPrev");
      var e = $.Event("keydown", {which: Keycodes.K, target: {type: "div"}});
      this.view._onHotkeyDown(e);
      expect(this.view.gotoPrev).toHaveBeenCalled();
    });

    it("'gotoPrev' should call 'selectPost'", function(){
      spyOn(this.view, 'selectPost');
      this.view.gotoPrev();
      expect(this.view.selectPost).toHaveBeenCalled();
    });

    it("shouldn't do anything if the user types in an input field", function(){
      spyOn(this.view, 'gotoPrev');
      spyOn(this.view, 'selectPost');
      var e = $.Event("keydown", { which: Keycodes.K, target: {type: "textarea"} });
      this.view._onHotkeyDown(e);
      expect(this.view.gotoPrev).not.toHaveBeenCalled();
      expect(this.view.selectPost).not.toHaveBeenCalled();
    });
  });

  describe("pressing 'c'", function(){
    it("should click on the comment-button if not pressed in an input field", function(){
      spyOn(this.view, 'commentSelected');
  describe("_onHotkeyUp", function() {
    it("calls commentSelected when the user pressed 'C'", function() {
      spyOn(this.view, "commentSelected");
      var e = $.Event("keyup", {which: Keycodes.C, target: {type: "div"}});
      this.view._onHotkeyUp(e);
      expect(this.view.commentSelected).toHaveBeenCalled();
    });

    it("shouldn't do anything if the user types in an input field", function(){
      spyOn(this.view, 'commentSelected');
      var e = $.Event("keyup", { which: Keycodes.C, target: {type: "textarea"} });
      this.view._onHotkeyUp(e);
      expect(this.view.commentSelected).not.toHaveBeenCalled();
    });
  });

  describe("pressing 'l'", function(){
    it("should click on the like-button if not pressed in an input field", function(){
      spyOn(this.view, 'likeSelected');
    it("calls likeSelected when the user pressed 'L'", function() {
      spyOn(this.view, "likeSelected");
      var e = $.Event("keyup", {which: Keycodes.L, target: {type: "div"}});
      this.view._onHotkeyUp(e);
      expect(this.view.likeSelected).toHaveBeenCalled();
    });

    it("shouldn't do anything if the user types in an input field", function(){
      spyOn(this.view, 'likeSelected');
      var e = $.Event("keyup", { which: Keycodes.L, target: {type: "textarea"} });
    it("calls expandSelected when the user pressed 'M'", function() {
      spyOn(this.view, "expandSelected");
      var e = $.Event("keyup", {which: Keycodes.M, target: {type: "div"}});
      this.view._onHotkeyUp(e);
      expect(this.view.likeSelected).not.toHaveBeenCalled();
    });
      expect(this.view.expandSelected).toHaveBeenCalled();
    });

  describe("pressing 'r'", function(){
    it("should click on the reshare-button if not pressed in an input field", function(){
      spyOn(this.view, 'reshareSelected');
      var e = $.Event("keyup", { which: Keycodes.R, target: {type: "div"} });
    it("calls openFirstLinkSelected when the user pressed 'O'", function() {
      spyOn(this.view, "openFirstLinkSelected");
      var e = $.Event("keyup", {which: Keycodes.O, target: {type: "div"}});
      this.view._onHotkeyUp(e);
      expect(this.view.reshareSelected).toHaveBeenCalled();
      expect(this.view.openFirstLinkSelected).toHaveBeenCalled();
    });

    it("shouldn't do anything if the user types in an input field", function(){
      spyOn(this.view, 'reshareSelected');
      var e = $.Event("keyup", { which: Keycodes.R, target: {type: "textarea"} });
    it("calls reshareSelected when the user pressed 'R'", function() {
      spyOn(this.view, "reshareSelected");
      var e = $.Event("keyup", {which: Keycodes.R, target: {type: "div"}});
      this.view._onHotkeyUp(e);
      expect(this.view.reshareSelected).not.toHaveBeenCalled();
    });
      expect(this.view.reshareSelected).toHaveBeenCalled();
    });

  describe("pressing 'm'", function(){
    it("should click on the more-button if not pressed in an input field", function(){
      spyOn(this.view, 'expandSelected');
      var e = $.Event("keyup", { which: Keycodes.M, target: {type: "div"} });
      this.view._onHotkeyUp(e);
      expect(this.view.expandSelected).toHaveBeenCalled();
  });

    it("shouldn't do anything if the user types in an input field", function(){
      spyOn(this.view, 'expandSelected');
      var e = $.Event("keyup", { which: Keycodes.M, target: {type: "textarea"} });
      this.view._onHotkeyUp(e);
      expect(this.view.expandSelected).not.toHaveBeenCalled();
    });
  describe("gotoNext", function() {
    it("calls selectPost", function() {
      spyOn(this.view, "selectPost");
      this.view.gotoNext();
      expect(this.view.selectPost).toHaveBeenCalled();
    });

  describe("pressing 'o'", function(){
    it("should click on the more-button if not pressed in an input field", function(){
      spyOn(this.view, 'openFirstLinkSelected');
      var e = $.Event("keyup", { which: Keycodes.O, target: {type: "div"} });
      this.view._onHotkeyUp(e);
      expect(this.view.openFirstLinkSelected).toHaveBeenCalled();
  });

    it("shouldn't do anything if the user types in an input field", function(){
      spyOn(this.view, 'openFirstLinkSelected');
      var e = $.Event("keyup", { which: Keycodes.O, target: {type: "textarea"} });
      this.view._onHotkeyUp(e);
      expect(this.view.openFirstLinkSelected).not.toHaveBeenCalled();
  describe("gotoPrev", function() {
    it("calls selectPost", function() {
      spyOn(this.view, "selectPost");
      this.view.gotoPrev();
      expect(this.view.selectPost).toHaveBeenCalled();
    });
  });
});