forked from autonome/Jetpack-Modules
-
Notifications
You must be signed in to change notification settings - Fork 1
/
commands.js
132 lines (115 loc) · 3.62 KB
/
commands.js
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
/*
Module for searching available commands in the browser.
Allows searching and execution of commands in Firefox, such as
'Back', 'Zoom In', 'Reload'.
Example that adds buttons to the add-on bar for every command,
which trigger the command when clicked:
const widget = require("widget");
const commands = require("commands");
commands.search("", function(command) {
widget.Widget({
label: command.alias,
content: command.alias,
onClick: command.execute
});
});
API
The 'search' method takes two parameters. the first is a string of text
to match against command names. For example, "zo" will match the commands
"Zoom In" and "Zoom Out". The second parameter is a callback that'll be
passed the command objects for all commands matching the search. The command
object has an 'alias' property, which contains a label used in the application
to refer to the command. The command object has an 'execute' method which
will trigger the command.
Implementation
The module enumerates all <command> elements found in the active browser
window, and then searches for any element in the browser that has a
command attribute with that command's id, storing the item's label
attribute value. The DOM traveral is only done once, on the first invocation
of the 'search' method.
TODO:
* find all elements with @oncommand, and log their string and id as a command
* for above, find keys, and walk back to consumers with strings, and log the
string + key id as a command
*/
let commands = {};
let aliases = {};
let aliasArray = [];
let cached = false;
function cacheCommands() {
let window = require("window-utils").activeBrowserWindow;
let document = window.document;
// harvest all basic commands
let els = document.querySelectorAll("command");
let len = els.length;
for (let i = 0; i < len; i++) {
let el = els[i];
let labels = [];
let subEls = document.querySelectorAll("*[command=\"" + el.id + "\"]");
if (subEls) {
for (let i = 0; i < subEls.length; i++) {
if (subEls[i].label) {
labels.push(subEls[i].label);
}
}
}
if (labels.length) {
commands[el.id] = el.id;
labels.forEach(function(label) {
aliases[label] = el.id;
aliasArray.push(label);
});
}
}
// harvest all elements with an oncommand attribute
els = document.querySelectorAll("*[oncommand]");
len = els.length;
for (let i = 0; i < len; i++) {
let el = els[i];
if (el.label && !aliases[el.label]) {
aliases[el.label] = el.id;
commands[el.id] = el.id;
aliasArray.push(el.label);
}
// ignore keys for now
/*
else {
let labels = [];
let subEls = document.querySelectorAll("*[command=\"" + el.id + "\"]");
if (subEls) {
for (let i = 0; i < subEls.length; i++) {
if (subEls[i].label) {
labels.push(subEls[i].label);
}
}
}
if (labels.length) {
commands[commandEl.id] = commandEl.id;
labels.forEach(function(label) aliases[label] = commandEl.id);
}
}
*/
}
aliasArray.sort(function(a, b) a - b);
}
function command(id, alias) {
this.alias = alias;
this.execute = function() {
if (commands[id]) {
let document = require("window-utils").activeBrowserWindow.document
let el = document.getElementById(id);
if (el)
el.doCommand();
}
};
}
exports.search = function(text, callback) {
if (!cached) {
cacheCommands();
cached = true;
}
for (var i in aliasArray) {
if (!text.length || (new RegExp(text, "i")).test(aliasArray[i]))
callback(new command(aliases[aliasArray[i]], aliasArray[i]));
}
};