Example of how to Open a KM Prompt from a JXA Script

Continuing the discussion from "No User Interaction Allowed" in Execute an AppleScript:

Let me put it all together:

##PURPOSE:

This example demonstrates one way to show two different kinds of Keyboard Maestro “Prompt” actions, from within a JavaScript for Automation (JXA) script.

  1. A typical “Information” prompt, with an “OK” button (the button text can be overridden).

  2. A typical “Confirmation” prompt, with “OK” and “Cancel” buttons (the button text can be overridden).

Here’s the complete example:

(function() {
    'use strict';

    var KMEngine = (function() {
        var _engineApp;

        function _escapeXml(str) {
            return str.replace(/[<>&'"]/g, function (c) {
                switch (c) {
                    case '<': return '&lt;';
                    case '>': return '&gt;';
                    case '&': return '&amp;';
                    case '\'': return '&apos;';
                    case '"': return '&quot;';
                }
            });
        }

        function _replaceAll(str, find, replace) {
            return str.replace(new RegExp(_escapeXml(find), 'g'), replace);
        }

        return {
            deleteVariable: function(name) {
                this.setVariable(name, "%Delete%");
            },

            doScript: function(uuidOrUniqueNameOrScript, parameter, timeout) {
                if (parameter) {
                    if (timeout) {
                        this.getEngineApp().doScript(uuidOrUniqueNameOrScript, { withParameter: parameter }, { timeout: timeout });
                    } else {
                        this.getEngineApp().doScript(uuidOrUniqueNameOrScript, { withParameter: parameter });
                    }
                } else {
                    if (timeout) {
                        this.getEngineApp().doScript(uuidOrUniqueNameOrScript, { timeout: timeout });
                    } else {
                        this.getEngineApp().doScript(uuidOrUniqueNameOrScript);
                    }
                }
            },

            getEngineAppName: function() {
                return "Keyboard Maestro Engine";
            },

            getEngineApp: function() {
                if (!_engineApp)
                    _engineApp = Application(this.getEngineAppName());
                return _engineApp;
            },

            getVariable: function(name, required) {
                var result = this.getEngineApp().getvariable(name);
                if (!result && required)
                    throw Error("Variable '" + name + "' is empty");
                return result;
            },

            setVariable: function(name, value) {
                this.getEngineApp().setvariable(name, {
                    to: value
                });
            },

            // You should pass values for "title" and "message". The rest have default values.
            showOkCancelMessagePrompt: function(title, message, okButtonText, cancelButtonText, resultVariableName) {
                title = title || "";
                message = message || "";
                okButtonText = okButtonText || "OK";
                cancelButtonText = cancelButtonText || "Cancel";
                resultVariableName = resultVariableName || "showOkCancelMessagePromptResult";
                var script =
                    '<dict> \n' +
                    '    <key>Actions</key> \n' +
                    '    <array> \n' +
                    '        <dict> \n' +
                    '            <key>MacroActionType</key> \n' +
                    '            <string>SetVariableToText</string> \n' +
                    '            <key>Text</key> \n' +
                    '            <string>##cancelButtonText##</string> \n' +
                    '            <key>Variable</key> \n' +
                    '            <string>##resultVariableName##</string> \n' +
                    '        </dict> \n' +
                    '        <dict> \n' +
                    '            <key>Buttons</key> \n' +
                    '            <array> \n' +
                    '                <dict> \n' +
                    '                    <key>Button</key> \n' +
                    '                    <string>##okButtonText##</string> \n' +
                    '                    <key>Cancel</key> \n' +
                    '                    <false/> \n' +
                    '                </dict> \n' +
                    '                <dict> \n' +
                    '                    <key>Button</key> \n' +
                    '                    <string>##cancelButtonText##</string> \n' +
                    '                    <key>Cancel</key> \n' +
                    '                    <true/> \n' +
                    '                </dict> \n' +
                    '            </array> \n' +
                    '            <key>MacroActionType</key> \n' +
                    '            <string>PromptForUserInput</string> \n' +
                    '            <key>Prompt</key> \n' +
                    '            <string>##message##</string> \n' +
                    '            <key>TimeOutAbortsMacro</key> \n' +
                    '            <true/> \n' +
                    '            <key>Title</key> \n' +
                    '            <string>##title##</string> \n' +
                    '            <key>Variables</key> \n' +
                    '            <array/> \n' +
                    '        </dict> \n' +
                    '        <dict> \n' +
                    '            <key>MacroActionType</key> \n' +
                    '            <string>SetVariableToText</string> \n' +
                    '            <key>Text</key> \n' +
                    '            <string>%Variable%Result Button%</string> \n' +
                    '            <key>Variable</key> \n' +
                    '            <string>##resultVariableName##</string> \n' +
                    '        </dict> \n' +
                    '    </array> \n' +
                    '    <key>MacroActionType</key> \n' +
                    '    <string>Group</string> \n' +
                    '    <key>TimeOutAbortsMacro</key> \n' +
                    '    <true/> \n' +
                    '</dict>';
                script = _replaceAll(script, "##title##", _escapeXml(title));
                script = _replaceAll(script, "##message##", _escapeXml(message));
                script = _replaceAll(script, "##okButtonText##", _escapeXml(okButtonText));
                script = _replaceAll(script, "##cancelButtonText##", _escapeXml(cancelButtonText));
                script = _replaceAll(script, "##resultVariableName##", _escapeXml(resultVariableName));
                this.doScript(script);
                var result = this.getVariable(resultVariableName);
                this.deleteVariable(resultVariableName);
                return result;
            },

            // You should pass values for "title" and "message". The rest have default values.
            showOkMessagePrompt: function(title, message, okButtonText) {
                title = title || "";
                message = message || "";
                okButtonText = okButtonText || "OK";
                var script =
                    '<dict> \n' +
                    '    <key>Buttons</key> \n' +
                    '    <array> \n' +
                    '        <dict> \n' +
                    '            <key>Button</key> \n' +
                    '            <string>##okButtonText##</string> \n' +
                    '        </dict> \n' +
                    '    </array> \n' +
                    '    <key>MacroActionType</key> \n' +
                    '    <string>PromptForUserInput</string> \n' +
                    '    <key>Prompt</key> \n' +
                    '    <string>##message##</string> \n' +
                    '    <key>TimeOutAbortsMacro</key> \n' +
                    '    <true/> \n' +
                    '    <key>Title</key> \n' +
                    '    <string>##title##</string> \n' +
                    '    <key>Variables</key> \n' +
                    '    <array/> \n' +
                    '</dict>';
                    script = script
                        .replace("##title##", _escapeXml(title))
                        .replace("##message##", _escapeXml(message))
                        .replace("##okButtonText##", _escapeXml(okButtonText));
                this.doScript(script);
            }

        };
    })();

    
    KMEngine.showOkMessagePrompt("My showOkMessagePrompt", "Default button text");
    KMEngine.showOkMessagePrompt("My showOkMessagePrompt", "Custom button text", "Done");


    var result = KMEngine.showOkCancelMessagePrompt("My showOkCancelMessagePrompt", "Default button text");
    console.log("Result(1) = '" + result + "'");
    
    result = KMEngine.showOkCancelMessagePrompt("My showOkCancelMessagePrompt", "Custom button text", "OkeyDokey", "No Way");
    console.log("Result(2) = '" + result + "'");
})();
1 Like

@DanThomas, thanks for posting and clarifying how to use.

BTW, I changed the KM “Category” to “macro”, and added some tags; all to make it easier to find this important topic.

1 Like

2 posts were split to a new topic: How to Create JavaScript Multiline String Literals (Template Literals)

Since it deserves its own topic, I moved the posts about multi-line strings to a new topic: