2c34939a43
Commands will be buffered and passed in to be fired on initialization. To suppress app launch, add the quiet flag to your command when firing the message from an extension. Fixes #122
98 lines
No EOL
2.9 KiB
JavaScript
98 lines
No EOL
2.9 KiB
JavaScript
define([
|
|
"util/text!config/commands.json",
|
|
"util/dom2"
|
|
], function(list) {
|
|
|
|
try {
|
|
list = JSON.parse(list);
|
|
} catch (e) {
|
|
console.error(e);
|
|
list = [];
|
|
}
|
|
|
|
/*
|
|
|
|
The command module is the heart of Caret's loosely-coupled modules. It
|
|
serves as an event bus for inter-module communication, but it also listens
|
|
to the DOM for click/change events and makes it easy to bind page interactions
|
|
to command callbacks.
|
|
|
|
Command is usually called as if synchronous, but it does support asynchronous
|
|
operation--it will pass a callback in to any subscribers, but will also
|
|
immediately pass back the return value (if any) from the those subscribers.
|
|
|
|
*/
|
|
|
|
var commands = {};
|
|
|
|
//commands can pass a callback, although most don't respond that way
|
|
var fire = function(command, argument, callback) {
|
|
if (!commands[command]) return;
|
|
var args = [].slice.call(arguments, 1);
|
|
//technically, a function as `argument` is a callback...
|
|
if (typeof argument == "function") {
|
|
callback = argument;
|
|
}
|
|
var registry = commands[command].slice();
|
|
registry.forEach(function(entry) {
|
|
var result = entry.callback.apply(null, args);
|
|
//immediately call back if sync-style return value was provided
|
|
if (typeof result !== "undefined" || entry.sync) {
|
|
//console.info("Immediate return from " + name, result);
|
|
if (callback) callback.call(null, result);
|
|
}
|
|
});
|
|
}
|
|
|
|
var register = function(command, listener, sync) {
|
|
if (!commands[command]) {
|
|
commands[command] = [];
|
|
}
|
|
//we allow a sync flag to be set for operations that will definitely return
|
|
commands[command].push({
|
|
callback: listener,
|
|
sync: sync
|
|
});
|
|
}
|
|
|
|
//delegate for all elements that have a command attribute
|
|
document.body.on("click", function(e) {
|
|
//cancel on inputs, selectboxes
|
|
if (["input", "select"].indexOf(e.target.tagName.toLowerCase()) >= 0) return;
|
|
if (e.button != 0) return;
|
|
//delegate all items with a command attribute
|
|
if (e.target.hasAttribute("command")) {
|
|
var command = e.target.getAttribute("command");
|
|
var arg = e.target.getAttribute("argument");
|
|
fire(command, arg);
|
|
e.preventDefault();
|
|
}
|
|
});
|
|
|
|
document.body.on("change", function(e) {
|
|
if (e.target.hasAttribute("command")) {
|
|
var command = e.target.getAttribute("command");
|
|
var arg = e.target.value;
|
|
fire(command, arg);
|
|
}
|
|
});
|
|
|
|
//register for startup and fire any commands that are pending
|
|
register("init:startup", function() {
|
|
if (window.launchCommands) {
|
|
window.launchCommands.forEach(function(bundle) {
|
|
fire(bundle.message.command, bundle.message.argument, bundle.sendResponse);
|
|
});
|
|
delete window.launchCommands;
|
|
}
|
|
});
|
|
|
|
var facade = {
|
|
fire: fire,
|
|
on: register,
|
|
list: list
|
|
};
|
|
|
|
return facade;
|
|
|
|
}); |