mirror of https://github.com/freeCodeCamp/devdocs
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
296 lines
6.4 KiB
296 lines
6.4 KiB
app.Shortcuts = class Shortcuts extends Events {
|
|
constructor() {
|
|
super();
|
|
this.onKeydown = this.onKeydown.bind(this);
|
|
this.onKeypress = this.onKeypress.bind(this);
|
|
this.isMac = $.isMac();
|
|
this.start();
|
|
}
|
|
|
|
start() {
|
|
$.on(document, "keydown", this.onKeydown);
|
|
$.on(document, "keypress", this.onKeypress);
|
|
}
|
|
|
|
stop() {
|
|
$.off(document, "keydown", this.onKeydown);
|
|
$.off(document, "keypress", this.onKeypress);
|
|
}
|
|
|
|
swapArrowKeysBehavior() {
|
|
return app.settings.get("arrowScroll");
|
|
}
|
|
|
|
spaceScroll() {
|
|
return app.settings.get("spaceScroll");
|
|
}
|
|
|
|
showTip() {
|
|
app.showTip("KeyNav");
|
|
return (this.showTip = null);
|
|
}
|
|
|
|
spaceTimeout() {
|
|
return app.settings.get("spaceTimeout");
|
|
}
|
|
|
|
onKeydown(event) {
|
|
if (this.buggyEvent(event)) {
|
|
return;
|
|
}
|
|
const result = (() => {
|
|
if (event.ctrlKey || event.metaKey) {
|
|
if (!event.altKey && !event.shiftKey) {
|
|
return this.handleKeydownSuperEvent(event);
|
|
}
|
|
} else if (event.shiftKey) {
|
|
if (!event.altKey) {
|
|
return this.handleKeydownShiftEvent(event);
|
|
}
|
|
} else if (event.altKey) {
|
|
return this.handleKeydownAltEvent(event);
|
|
} else {
|
|
return this.handleKeydownEvent(event);
|
|
}
|
|
})();
|
|
|
|
if (result === false) {
|
|
event.preventDefault();
|
|
}
|
|
}
|
|
|
|
onKeypress(event) {
|
|
if (
|
|
this.buggyEvent(event) ||
|
|
(event.charCode === 63 && document.activeElement.tagName === "INPUT")
|
|
) {
|
|
return;
|
|
}
|
|
if (!event.ctrlKey && !event.metaKey) {
|
|
const result = this.handleKeypressEvent(event);
|
|
if (result === false) {
|
|
event.preventDefault();
|
|
}
|
|
}
|
|
}
|
|
|
|
handleKeydownEvent(event, _force) {
|
|
if (
|
|
!_force &&
|
|
[37, 38, 39, 40].includes(event.which) &&
|
|
this.swapArrowKeysBehavior()
|
|
) {
|
|
return this.handleKeydownAltEvent(event, true);
|
|
}
|
|
|
|
if (
|
|
!event.target.form &&
|
|
((48 <= event.which && event.which <= 57) ||
|
|
(65 <= event.which && event.which <= 90))
|
|
) {
|
|
this.trigger("typing");
|
|
return;
|
|
}
|
|
|
|
switch (event.which) {
|
|
case 8:
|
|
if (!event.target.form) {
|
|
return this.trigger("typing");
|
|
}
|
|
break;
|
|
case 13:
|
|
return this.trigger("enter");
|
|
case 27:
|
|
this.trigger("escape");
|
|
return false;
|
|
case 32:
|
|
if (
|
|
event.target.type === "search" &&
|
|
this.spaceScroll() &&
|
|
(!this.lastKeypress ||
|
|
this.lastKeypress < Date.now() - this.spaceTimeout() * 1000)
|
|
) {
|
|
this.trigger("pageDown");
|
|
return false;
|
|
}
|
|
break;
|
|
case 33:
|
|
return this.trigger("pageUp");
|
|
case 34:
|
|
return this.trigger("pageDown");
|
|
case 35:
|
|
if (!event.target.form) {
|
|
return this.trigger("pageBottom");
|
|
}
|
|
break;
|
|
case 36:
|
|
if (!event.target.form) {
|
|
return this.trigger("pageTop");
|
|
}
|
|
break;
|
|
case 37:
|
|
if (!event.target.value) {
|
|
return this.trigger("left");
|
|
}
|
|
break;
|
|
case 38:
|
|
this.trigger("up");
|
|
if (typeof this.showTip === "function") {
|
|
this.showTip();
|
|
}
|
|
return false;
|
|
case 39:
|
|
if (!event.target.value) {
|
|
return this.trigger("right");
|
|
}
|
|
break;
|
|
case 40:
|
|
this.trigger("down");
|
|
if (typeof this.showTip === "function") {
|
|
this.showTip();
|
|
}
|
|
return false;
|
|
case 191:
|
|
if (!event.target.form) {
|
|
this.trigger("typing");
|
|
return false;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
handleKeydownSuperEvent(event) {
|
|
switch (event.which) {
|
|
case 13:
|
|
return this.trigger("superEnter");
|
|
case 37:
|
|
if (this.isMac) {
|
|
this.trigger("superLeft");
|
|
return false;
|
|
}
|
|
break;
|
|
case 38:
|
|
this.trigger("pageTop");
|
|
return false;
|
|
case 39:
|
|
if (this.isMac) {
|
|
this.trigger("superRight");
|
|
return false;
|
|
}
|
|
break;
|
|
case 40:
|
|
this.trigger("pageBottom");
|
|
return false;
|
|
case 188:
|
|
this.trigger("preferences");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
handleKeydownShiftEvent(event, _force) {
|
|
if (
|
|
!_force &&
|
|
[37, 38, 39, 40].includes(event.which) &&
|
|
this.swapArrowKeysBehavior()
|
|
) {
|
|
return this.handleKeydownEvent(event, true);
|
|
}
|
|
|
|
if (!event.target.form && 65 <= event.which && event.which <= 90) {
|
|
this.trigger("typing");
|
|
return;
|
|
}
|
|
|
|
switch (event.which) {
|
|
case 32:
|
|
this.trigger("pageUp");
|
|
return false;
|
|
case 38:
|
|
if (!getSelection()?.toString()) {
|
|
this.trigger("altUp");
|
|
return false;
|
|
}
|
|
break;
|
|
case 40:
|
|
if (!getSelection()?.toString()) {
|
|
this.trigger("altDown");
|
|
return false;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
handleKeydownAltEvent(event, _force) {
|
|
if (
|
|
!_force &&
|
|
[37, 38, 39, 40].includes(event.which) &&
|
|
this.swapArrowKeysBehavior()
|
|
) {
|
|
return this.handleKeydownEvent(event, true);
|
|
}
|
|
|
|
switch (event.which) {
|
|
case 9:
|
|
return this.trigger("altRight", event);
|
|
case 37:
|
|
if (!this.isMac) {
|
|
this.trigger("superLeft");
|
|
return false;
|
|
}
|
|
break;
|
|
case 38:
|
|
this.trigger("altUp");
|
|
return false;
|
|
case 39:
|
|
if (!this.isMac) {
|
|
this.trigger("superRight");
|
|
return false;
|
|
}
|
|
break;
|
|
case 40:
|
|
this.trigger("altDown");
|
|
return false;
|
|
case 67:
|
|
this.trigger("altC");
|
|
return false;
|
|
case 68:
|
|
this.trigger("altD");
|
|
return false;
|
|
case 70:
|
|
return this.trigger("altF", event);
|
|
case 71:
|
|
this.trigger("altG");
|
|
return false;
|
|
case 79:
|
|
this.trigger("altO");
|
|
return false;
|
|
case 82:
|
|
this.trigger("altR");
|
|
return false;
|
|
case 83:
|
|
this.trigger("altS");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
handleKeypressEvent(event) {
|
|
if (event.which === 63 && !event.target.value) {
|
|
this.trigger("help");
|
|
return false;
|
|
} else {
|
|
return (this.lastKeypress = Date.now());
|
|
}
|
|
}
|
|
|
|
buggyEvent(event) {
|
|
try {
|
|
event.target;
|
|
event.ctrlKey;
|
|
event.which;
|
|
return false;
|
|
} catch (error) {
|
|
return true;
|
|
}
|
|
}
|
|
};
|