1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
var SCROLL_STEP_SIZE = 60; // Pixels
var keyCodes = { ESC: 27 };
var insertMode = false;
var keyPort;
function scrollToBottom() { window.scrollTo(0, document.body.scrollHeight); }
function scrollToTop() { window.scrollTo(0, 0); }
function scrollUp() { window.scrollBy(0, -1 * SCROLL_STEP_SIZE); }
function scrollDown() { window.scrollBy(0, SCROLL_STEP_SIZE); }
function scrollPageUp() { window.scrollBy(0, -6 * SCROLL_STEP_SIZE); }
function scrollPageDown() { window.scrollBy(0, 6 * SCROLL_STEP_SIZE); }
function scrollLeft() { window.scrollBy(-1 * SCROLL_STEP_SIZE, 0); }
function scrollRight() { window.scrollBy(SCROLL_STEP_SIZE, 0); }
function reload() { window.location.reload(); }
function goBack() { history.back(); }
function goForward() { history.forward(); }
function initializeFrontend() {
document.addEventListener("keydown", onKeydown);
document.addEventListener("focus", onFocusCapturePhase, true);
document.addEventListener("blur", onBlurCapturePhase, true);
// Send the key to the key handler in the background page.
keyPort = chrome.extension.connect({name: "keyDown"});
chrome.extension.onConnect.addListener(function (port, name) {
if (port.name == "executePageCommand") {
port.onMessage.addListener(function (args) {
if (this[args.command])
{
for (var i = 0; i < args.count; i++) { this[args.command].call(); }
}
});
}
else if (port.name == "getScrollPosition") {
port.onMessage.addListener(function (args) {
var scrollPort = chrome.extension.connect({ name: "returnScrollPosition" });
scrollPort.postMessage({
scrollX: window.scrollX,
scrollY: window.scrollY,
currentTab: args.currentTab
});
});
} else if (port.name == "setScrollPosition") {
port.onMessage.addListener(function (args) {
if (args.scrollX > 0 || args.scrollY > 0) { window.scrollBy(args.scrollX, args.scrollY); }
});
}
});
};
/**
* Sends everything except i & ESC to the handler in background_page. i & ESC are special because they control
* insert mode which is local state to the page. The key will be are either a single ascii letter or a
* key-modifier pair, e.g. <c-a> for control a.
*
* Note that some keys will only register keydown events and not keystroke events, e.g. ESC.
*/
function onKeydown(event) {
var keyChar = "";
// Ignore modifier keys by themselves.
if (event.keyCode > 31 && event.keyCode < 127) {
keyChar = String.fromCharCode(event.keyCode).toLowerCase();
if (event.shiftKey)
keyChar = keyChar.toUpperCase();
if (event.ctrlKey)
keyChar = "<c-" + keyChar + ">";
}
if (insertMode && event.keyCode == keyCodes.ESC)
exitInsertMode();
else if (!insertMode && keyChar == "i")
enterInsertMode();
else if (!insertMode && keyChar)
keyPort.postMessage(keyChar);
}
function onFocusCapturePhase(event) {
if (event.target.tagName == "INPUT" || event.target.tagName == "TEXTAREA")
enterInsertMode();
}
function onBlurCapturePhase(event) {
if (event.target.tagName == "INPUT" || event.target.tagName == "TEXTAREA")
exitInsertMode();
}
function enterInsertMode() {
insertMode = true;
HUD.show("Insert mode");
}
function exitInsertMode() {
insertMode = false;
HUD.hide();
}
HUD = {
show:function(text) {
HUD.displayElement().innerHTML = text;
HUD.displayElement().style.display = "";
},
/*
* Retrieves the HUD HTML element, creating it if necessary.
*/
displayElement: function() {
if (!HUD._displayElement) {
var element = document.createElement("div");
element.innerHTML = "howdy";
element.style.position = "fixed";
element.style.bottom = "0px";
element.style.left = "10px";
element.style.backgroundColor = " #e5e5e5";
element.style.maxWidth = "400px";
element.style.fontSize = "11px";
element.style.padding = "3px";
element.style.border = "1px solid #cccccc";
element.style.borderBottomWidth = "0px";
// element.style.fontFamily = "monospace";
document.body.appendChild(element);
HUD._displayElement = element
}
return HUD._displayElement
},
hide: function() {
HUD.displayElement().style.display = "none";
}
};
// Prevent our content script from being run on iframes -- only allow it to run on the top level DOM "window".
// TODO(philc): We don't want to process multiple keyhandlers etc. when embedded on a page containing IFrames.
// This should be revisited, because sometimes we *do* want to listen inside of the currently focused iframe.
var isIframe = (window.self != window.parent);
if (!isIframe)
initializeFrontend();
|