Question about window.KeyboardMaestro.Cancel() in a Custom HTML Prompt,

@peter - Does the code following a call to window.KeyboardMaestro.Cancel() ever get executed?

Here's an example:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Example</title>
</head>
<body>
    <button id="btnClose">Close</button>
    <button id="btnCancel">Cancel</button>

    <script>
        function KMWindow() {
            document.getElementById("btnClose").addEventListener("click", function() {
                window.KeyboardMaestro.Submit()
                console.log("Got here (close)");
            });

            document.getElementById("btnCancel").addEventListener("click", function() {
                window.KeyboardMaestro.Cancel()
                console.log("Got here (cancel)");
            });
        }
    </script>
</body>
</html>

Will either "console.log" ever get called? For clarity, I'm just using "console.log" as an example. I know I'd never get a chance to see it.

My specific reason for asking is actually more nuanced:


function example() {
    try {
        doSomethingBad();
    } catch (e) {
        handleError(e);
    }

    doSomethingElse();
}

function doSomethingBad() {
    throw new Error(`Bad!`);
}

function doSomethingElse() {
    // do some other code
}

function handleError(e) {
    // log error using some logging method
    window.KeyboardMaestro.Cancel(e.message);
}

In the above example, I'd like to assume that when I call handleError() in the catch block of the example() function, the call to doSomethingElse() will never happen.

So that's why I ask.

You are missing semicolons after the window.KeyboardMaestro.Cancel()

Will it get executed? I honestly don't know, and I would not want to guarantee it one way or the other. Both options are quite possible.

I would not rely on the behaviour either way.

1 Like

The semi-colons aren't necessary, and it was just an example.

Thanks for the answer - I'm currently not expecting either, so that's fine.

Aren't they? I thought JavaScript has to have ; at the end of statements…?

Oh wow, they are just optional, how absolutely weird.

TIL.

Yeah, JavaScript is strange in a lot of ways. But it's still the most enjoyable language I've ever used.

1 Like

Cannot help but throw in this mostly non sequitur..

I used to work a lot with Oracle databases. SQL statements were supposed to end with the semicolon.

Once in a while I would forget it, and the engine would throw an error: "Statement does not end with a semicolon."

That infuriated me every time.

1 Like

I've totally come across this, and my response was always the same as what I suspect your's was. "Well, if you know it's missing a semicolon, then just add one!"

3 Likes

Which is fine, right up until it makes your broken SQL correct and executes the accidental DROP ALL TABI_ES command (which even in text I was not game to write without a deliberate typo!)

3 Likes

This might be of interest to the group that use external code editors to create the content for the Custom HTML Prompt. It contains a function for testing whether the JS is being run within the Custom HTML Prompt environment or not.

I was also playing with various formats to define the anonymous arrow function, pick your poison. There is a link to the pertinent MDN documentation included.

The original example defined the function but never called it. Not sure whether it was supposed to be triggered elsewhere by a button or link in html. In any case I just commented out the function and let the two definitions live at the global level.

In relation to the addition or omission of the semicolons. One small advantage of using an IDE (Integrated Development Environment), like VS Code, is the ability to add extensions like “Prettier” which will automatically format your code in a preferred manner. So even if you missed a semi-colon it could be added in when you save the file. The discussion about semicolons was a hot topic after the option was added to the JavaScript spec. Traditionally the semicolons were required. Here is a relatively recent link to commentary on that issue.

https://javascripttoday.com/blog/to-semicolon-or-not-in-javascript/

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Example</title>
  </head>
  <body>
    <button id="btnClose">Close</button>
    <button id="btnCancel">Cancel</button>

    <script>
      // A test for determining the availability of Keyboard Maestro
      // This allows testing of JavaScript in both
      // VS Code and Keyboard Maestro Custom
      // Floating HTML Prompts.
      // The resulting code can be copied directly
      // from VS Code into KM without adjustments...

      /*

      // There is a good explanation of 
      // 'Arrow functions' at the following URL
      // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

      // Traditional ES5 method

      const kmAvailable = availabilityTest();
      
      function availabilityTest() {
        const test = window.KeyboardMaestro;
        if (typeof test != 'undefined') {
          return true;
        } else {
          return false;
        }
      }
        */

      /*

      // Showing progression thru various ES6 equivalent versions

      // NOTE: the final parentheses at the end of definition, 
      // are required to call the defined function, and 
      // get the function result placed into the constant.

      const kmAvailable = (() => {
        const test = window.KeyboardMaestro;
        if (typeof test != 'undefined') {
          return true;
        } else {
          return false;
        }
      })();

      */

      /*
   
      // Replacement of if statement with tenary operator

      const kmAvailable = (() => {
         const test = window.KeyboardMaestro
         return typeof test != 'undefined' ? true : false
      })();
      */

      /*
      // Eliminated the intermediate variable, i.e., test

      const kmAvailable = (() => {
         return typeof (window.KeyboardMaestro) != 'undefined' ? true : false
      })();
      */

      // Removed the function block as it only contains one statement

      const kmAvailable = (() =>
        typeof window.KeyboardMaestro != 'undefined' ? true : false)();

      console.log(kmAvailable);

      // Bind buttons to JS functionality

      //function KMWindow() {
      const btnClose = document.getElementById('btnClose');
      btnClose.addEventListener('click', function () {
        if (kmAvailable) window.KeyboardMaestro.Submit();
        console.log('Got here (close)');
      });

      const btnCancel = document.getElementById('btnCancel');
      btnCancel.addEventListener('click', function () {
        if (kmAvailable) window.KeyboardMaestro.Cancel();
        console.log('Got here (cancel)');
      });
      // }

      // KMWindow();
    </script>
  </body>
</html>

1 Like