CustomHTMLPrompt - Get KM Macro Response
REQUIRES
- The macro "Execute Dynamic Javascript in Browser" must be installed.
THE PROBLEM:
Custom HTML Prompts (hereafter referred to as "The Prompt") can trigger Keyboard Maestro macros using window.KeyboardMaestro.Trigger()
. Unfortunately, this does not return a result. You can't get a response back using AppleScript, either.
THE SOLUTION:
When the Prompt triggers the macro, the macro can then use Execute JavaScript in Browser
to return the result.
There's several ways to accomplish this, but here's a method that uses an asynchronous method so your code can use an "await", and it has a timeout in case the macro fails:
THE CODE:
Click to expand
In this code, I wrote a function called "roundTrip". It triggers the macro, and waits for the response. It includes a timeout for safety, in case the macro crashes.
Here's the basic code, without anything extraneous:
Button Element:
Clicking this button calls the btnTriggerClicked
event.
<button id="btnTrigger" type="button" onclick="btnTriggerClicked()">Trigger</button>
Button Clicked Event:
This is an async
function, which allows us to use the await
keyword, so our code will stop and wait for the response.
async function btnTriggerClicked(action = "") {
console.log(`btnTriggerClicked: triggering the macro and waiting for the response`);
const result = await roundTrip();
console.log(`btnTriggerClicked: Got result: "${result}"`);
}
function roundTrip()
This function sets up the parameter triggerData
for the macro, then triggers the macro, then returns the result. It uses a timeout of 3000 ms, or 3 seconds.
async function roundTrip() {
try {
var triggerData = {
kmwindowid: "GetKMResponse CustomHTMLPrompt",
text: "This is a test"
};
window.KeyboardMaestro.Trigger("4FE6B6EE-0583-4D1E-A5E4-1A12A86EA53C", JSON.stringify(triggerData));
const result = await getResponse(3000);
return result;
} catch (e) {
console.log(`Error in roundTrip: ${e.message}`);
return null;
}
}
function getResponse(timeout)
This is where the magic happens. You don't need to understand exactly how it works.
Suffice it to say that it sets up a timer for the timeout portion, and waits for a custom event we're calling "kmResponse".
function getResponse(timeout) {
return new Promise(function(resolve, reject) {
const timer = setTimeout(() => {
document.removeEventListener('kmResponse', handleResponse);
console.error(`Response timed out`);
reject(new Error("Response timed out"));
}, timeout);
function handleResponse(e) {
clearTimeout(timer);
console.log(`event listener got response "${e.detail}"`);
document.removeEventListener('kmResponse', handleResponse);
resolve(e.detail);
}
document.addEventListener('kmResponse', handleResponse);
});
}
function insertResponse(response)
This is what the macro calls using Execure JavaScript in Browser
. The function takes the parameter, and fires off the custom event "kmResponse" that getResponse
(above) is waiting for:
function insertResponse(response) {
console.log(`insertResponse called with "${response}"`)
document.dispatchEvent(new CustomEvent("kmResponse", { detail: response }));
}
The Macro
And finally, here's the macro:
INSTALLATION
UPGRADE INSTRUCTIONS:
- Delete the old macros, or just delete the entire group.
- Install the new macros.
Download the zip file, unzip it, and double-click the .kmmacros file.
CustomHTMLPrompt - Get KM Macro Response.v1.0.kmmacros.zip (5.1 KB)