Skip to content

Commit 35aa0ba

Browse files
svbergeremdenschub
authored andcommitted
Refactor stream shortcuts
closes #7127
1 parent 0a264c1 commit 35aa0ba

5 files changed

Lines changed: 110 additions & 109 deletions

File tree

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Note: Although this is a minor release, the configuration file changed because t
1515
* Refactored post interactions on the single post view [#7089](https://github.com/diaspora/diaspora/pull/7089)
1616
* Extract inline JavaScript [#7113](https://github.com/diaspora/diaspora/pull/7113)
1717
* Port conversations inbox to backbone.js [#7108](https://github.com/diaspora/diaspora/pull/7108)
18+
* Refactored stream shortcuts for more flexibility [#7127](https://github.com/diaspora/diaspora/pull/7127)
1819

1920
## Bug fixes
2021
* Post comments no longer get collapsed when interacting with a post [#7040](https://github.com/diaspora/diaspora/pull/7040)
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later
2+
(function() {
3+
app.helpers.Shortcuts = function(evtname, fn) {
4+
var textAcceptingInputTypes = [
5+
"color",
6+
"date",
7+
"datetime",
8+
"datetime-local",
9+
"email",
10+
"month",
11+
"number",
12+
"password",
13+
"range",
14+
"search",
15+
"select",
16+
"text",
17+
"textarea",
18+
"time",
19+
"url",
20+
"week"
21+
];
22+
23+
$("body").on(evtname, function(event) {
24+
// make sure that the user is not typing in an input field
25+
if (textAcceptingInputTypes.indexOf(event.target.type) === -1) {
26+
fn(event);
27+
}
28+
});
29+
};
30+
})();
31+
// @license-end

app/assets/javascripts/app/views/stream/shortcuts.js

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,12 @@
33
app.views.StreamShortcuts = Backbone.View.extend({
44
_headerSize: 60,
55

6-
events: {
7-
"keydown": "_onHotkeyDown",
8-
"keyup": "_onHotkeyUp"
6+
initialize: function() {
7+
app.helpers.Shortcuts("keydown", this._onHotkeyDown.bind(this));
8+
app.helpers.Shortcuts("keyup", this._onHotkeyUp.bind(this));
99
},
1010

1111
_onHotkeyDown: function(event) {
12-
//make sure that the user is not typing in an input field
13-
var textAcceptingInputTypes = ["textarea", "select", "text", "password", "number", "email", "url", "range", "date", "month", "week", "time", "datetime", "datetime-local", "search", "color"];
14-
if(jQuery.inArray(event.target.type, textAcceptingInputTypes) > -1){
15-
return;
16-
}
17-
1812
// trigger the events based on what key was pressed
1913
switch (String.fromCharCode( event.which ).toLowerCase()) {
2014
case "j":
@@ -28,12 +22,6 @@ app.views.StreamShortcuts = Backbone.View.extend({
2822
},
2923

3024
_onHotkeyUp: function(event) {
31-
//make sure that the user is not typing in an input field
32-
var textAcceptingInputTypes = ["textarea", "select", "text", "password", "number", "email", "url", "range", "date", "month", "week", "time", "datetime", "datetime-local", "search", "color"];
33-
if(jQuery.inArray(event.target.type, textAcceptingInputTypes) > -1){
34-
return;
35-
}
36-
3725
// trigger the events based on what key was pressed
3826
switch (String.fromCharCode( event.which ).toLowerCase()) {
3927
case "c":
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
describe("app.helpers.Shortcuts", function() {
2+
it("calls the function when the event has been fired outside of an input field", function() {
3+
var spy = jasmine.createSpy();
4+
spec.content().append("<div class='hotkey-div'></div>");
5+
app.helpers.Shortcuts("keydown", spy);
6+
$(".hotkey-div").trigger("keydown");
7+
expect(spy).toHaveBeenCalled();
8+
});
9+
10+
it("doesn't call the function when the event has been fired in an input field", function() {
11+
var spy = jasmine.createSpy();
12+
spec.content().append("<textarea class='hotkey-textarea'></textarea>");
13+
app.helpers.Shortcuts("keydown", spy);
14+
$(".hotkey-textarea").trigger("keydown");
15+
expect(spy).not.toHaveBeenCalled();
16+
});
17+
});

spec/javascripts/app/views/stream/shortcuts_spec.js

Lines changed: 58 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -13,131 +13,95 @@ describe("app.views.StreamShortcuts", function () {
1313
expect(spec.content().find("div.stream-element.loaded").length).toBe(2);
1414
});
1515

16-
describe("pressing 'j'", function(){
17-
it("should call 'gotoNext' if not pressed in an input field", function(){
18-
spyOn(this.view, 'gotoNext');
19-
var e = $.Event("keydown", { which: Keycodes.J, target: {type: "div"} });
20-
this.view._onHotkeyDown(e);
21-
expect(this.view.gotoNext).toHaveBeenCalled();
22-
});
23-
24-
it("'gotoNext' should call 'selectPost'", function(){
25-
spyOn(this.view, 'selectPost');
26-
this.view.gotoNext();
27-
expect(this.view.selectPost).toHaveBeenCalled();
28-
});
29-
30-
it("shouldn't do anything if the user types in an input field", function(){
31-
spyOn(this.view, 'gotoNext');
32-
spyOn(this.view, 'selectPost');
33-
var e = $.Event("keydown", { which: Keycodes.J, target: {type: "textarea"} });
34-
this.view._onHotkeyDown(e);
35-
expect(this.view.gotoNext).not.toHaveBeenCalled();
36-
expect(this.view.selectPost).not.toHaveBeenCalled();
16+
describe("initialize", function() {
17+
it("setups the shortcuts", function() {
18+
spyOn(app.helpers, "Shortcuts").and.callThrough();
19+
spyOn(app.views.StreamShortcuts.prototype, "_onHotkeyDown");
20+
spyOn(app.views.StreamShortcuts.prototype, "_onHotkeyUp");
21+
this.view = new app.views.StreamShortcuts({el: $(document)});
22+
expect(app.helpers.Shortcuts.calls.count()).toBe(2);
23+
24+
$("body").trigger($.Event("keydown", {which: Keycodes.J, target: {type: "textarea"}}));
25+
$("body").trigger($.Event("keyup", {which: Keycodes.J, target: {type: "textarea"}}));
26+
expect(app.views.StreamShortcuts.prototype._onHotkeyDown).not.toHaveBeenCalled();
27+
expect(app.views.StreamShortcuts.prototype._onHotkeyUp).not.toHaveBeenCalled();
28+
29+
var e = $.Event("keydown", {which: Keycodes.J, target: {type: "div"}});
30+
$("body").trigger(e);
31+
expect(app.views.StreamShortcuts.prototype._onHotkeyDown).toHaveBeenCalledWith(e);
32+
33+
e = $.Event("keyup", {which: Keycodes.J, target: {type: "div"}});
34+
$("body").trigger(e);
35+
expect(app.views.StreamShortcuts.prototype._onHotkeyUp).toHaveBeenCalledWith(e);
3736
});
3837
});
3938

40-
describe("pressing 'k'", function(){
41-
it("should call 'gotoPrev' if not pressed in an input field", function(){
42-
spyOn(this.view, 'gotoPrev');
43-
var e = $.Event("keydown", { which: Keycodes.K, target: {type: "div"} });
39+
describe("_onHotkeyDown", function() {
40+
it("calls goToNext when the user pressed 'J'", function() {
41+
spyOn(this.view, "gotoNext");
42+
var e = $.Event("keydown", {which: Keycodes.J, target: {type: "div"}});
4443
this.view._onHotkeyDown(e);
45-
expect(this.view.gotoPrev).toHaveBeenCalled();
46-
});
47-
48-
it("'gotoPrev' should call 'selectPost'", function(){
49-
spyOn(this.view, 'selectPost');
50-
this.view.gotoPrev();
51-
expect(this.view.selectPost).toHaveBeenCalled();
44+
expect(this.view.gotoNext).toHaveBeenCalled();
5245
});
5346

54-
it("shouldn't do anything if the user types in an input field", function(){
55-
spyOn(this.view, 'gotoPrev');
56-
spyOn(this.view, 'selectPost');
57-
var e = $.Event("keydown", { which: Keycodes.K, target: {type: "textarea"} });
47+
it("calls gotoPrev when the user pressed 'K'", function() {
48+
spyOn(this.view, "gotoPrev");
49+
var e = $.Event("keydown", {which: Keycodes.K, target: {type: "div"}});
5850
this.view._onHotkeyDown(e);
59-
expect(this.view.gotoPrev).not.toHaveBeenCalled();
60-
expect(this.view.selectPost).not.toHaveBeenCalled();
51+
expect(this.view.gotoPrev).toHaveBeenCalled();
6152
});
6253
});
6354

64-
describe("pressing 'c'", function(){
65-
it("should click on the comment-button if not pressed in an input field", function(){
66-
spyOn(this.view, 'commentSelected');
67-
var e = $.Event("keyup", { which: Keycodes.C, target: {type: "div"} });
55+
describe("_onHotkeyUp", function() {
56+
it("calls commentSelected when the user pressed 'C'", function() {
57+
spyOn(this.view, "commentSelected");
58+
var e = $.Event("keyup", {which: Keycodes.C, target: {type: "div"}});
6859
this.view._onHotkeyUp(e);
6960
expect(this.view.commentSelected).toHaveBeenCalled();
7061
});
7162

72-
it("shouldn't do anything if the user types in an input field", function(){
73-
spyOn(this.view, 'commentSelected');
74-
var e = $.Event("keyup", { which: Keycodes.C, target: {type: "textarea"} });
75-
this.view._onHotkeyUp(e);
76-
expect(this.view.commentSelected).not.toHaveBeenCalled();
77-
});
78-
});
79-
80-
describe("pressing 'l'", function(){
81-
it("should click on the like-button if not pressed in an input field", function(){
82-
spyOn(this.view, 'likeSelected');
83-
var e = $.Event("keyup", { which: Keycodes.L, target: {type: "div"} });
63+
it("calls likeSelected when the user pressed 'L'", function() {
64+
spyOn(this.view, "likeSelected");
65+
var e = $.Event("keyup", {which: Keycodes.L, target: {type: "div"}});
8466
this.view._onHotkeyUp(e);
8567
expect(this.view.likeSelected).toHaveBeenCalled();
8668
});
8769

88-
it("shouldn't do anything if the user types in an input field", function(){
89-
spyOn(this.view, 'likeSelected');
90-
var e = $.Event("keyup", { which: Keycodes.L, target: {type: "textarea"} });
70+
it("calls expandSelected when the user pressed 'M'", function() {
71+
spyOn(this.view, "expandSelected");
72+
var e = $.Event("keyup", {which: Keycodes.M, target: {type: "div"}});
9173
this.view._onHotkeyUp(e);
92-
expect(this.view.likeSelected).not.toHaveBeenCalled();
74+
expect(this.view.expandSelected).toHaveBeenCalled();
9375
});
94-
});
9576

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

104-
it("shouldn't do anything if the user types in an input field", function(){
105-
spyOn(this.view, 'reshareSelected');
106-
var e = $.Event("keyup", { which: Keycodes.R, target: {type: "textarea"} });
84+
it("calls reshareSelected when the user pressed 'R'", function() {
85+
spyOn(this.view, "reshareSelected");
86+
var e = $.Event("keyup", {which: Keycodes.R, target: {type: "div"}});
10787
this.view._onHotkeyUp(e);
108-
expect(this.view.reshareSelected).not.toHaveBeenCalled();
88+
expect(this.view.reshareSelected).toHaveBeenCalled();
10989
});
11090
});
11191

112-
describe("pressing 'm'", function(){
113-
it("should click on the more-button if not pressed in an input field", function(){
114-
spyOn(this.view, 'expandSelected');
115-
var e = $.Event("keyup", { which: Keycodes.M, target: {type: "div"} });
116-
this.view._onHotkeyUp(e);
117-
expect(this.view.expandSelected).toHaveBeenCalled();
118-
});
119-
120-
it("shouldn't do anything if the user types in an input field", function(){
121-
spyOn(this.view, 'expandSelected');
122-
var e = $.Event("keyup", { which: Keycodes.M, target: {type: "textarea"} });
123-
this.view._onHotkeyUp(e);
124-
expect(this.view.expandSelected).not.toHaveBeenCalled();
92+
describe("gotoNext", function() {
93+
it("calls selectPost", function() {
94+
spyOn(this.view, "selectPost");
95+
this.view.gotoNext();
96+
expect(this.view.selectPost).toHaveBeenCalled();
12597
});
12698
});
12799

128-
describe("pressing 'o'", function(){
129-
it("should click on the more-button if not pressed in an input field", function(){
130-
spyOn(this.view, 'openFirstLinkSelected');
131-
var e = $.Event("keyup", { which: Keycodes.O, target: {type: "div"} });
132-
this.view._onHotkeyUp(e);
133-
expect(this.view.openFirstLinkSelected).toHaveBeenCalled();
134-
});
135-
136-
it("shouldn't do anything if the user types in an input field", function(){
137-
spyOn(this.view, 'openFirstLinkSelected');
138-
var e = $.Event("keyup", { which: Keycodes.O, target: {type: "textarea"} });
139-
this.view._onHotkeyUp(e);
140-
expect(this.view.openFirstLinkSelected).not.toHaveBeenCalled();
100+
describe("gotoPrev", function() {
101+
it("calls selectPost", function() {
102+
spyOn(this.view, "selectPost");
103+
this.view.gotoPrev();
104+
expect(this.view.selectPost).toHaveBeenCalled();
141105
});
142106
});
143107
});

0 commit comments

Comments
 (0)