Missing HTMLPrompt, AlertButton and PromptButton tokens

In most respects the Custom HTML Prompt action is working as it should, but as shown in the image below the %HTMLResult% token (along with %AlertButton% and %PromptButton% tokens) is missing.

What am I misunderstanding?

@peternlewis I've gotten views but no feedback on this. I thought I would ask you directly. I'm running Version 10.1 on Monterey 12.3.1. Thanks.

Hold the Shift key to show the actual token names in the menu. Also hold the Option key down to get help on the token.

You can also type the token yourself, use the By Name… option which will find it easily enough, and type “%HTM” followed by the F5 key to auto-complete it.

@peternlewis
Hi Peter. Thanks for that! But (as I always do with tokens in practice) I was typing out %HTMLResult% when I encountered the problem.

Let me give an example. Execute the following Custom HTML Prompt:


CODE:

<!doctype html>
<html>
<head>
<title>Test HTMLResult</title>
</head>
<body>

<form action="#" method="post">
<input id="radio_buton" type="radio" name="buttonvar" value="buttonvar set in HTML">Set buttonvar</input> 
<hr>
<button type="button" onclick="testFunc()" >OK</button>
</form>

<script>
function testFunc() {
	window.KeyboardMaestro.SetVariable("testvar","OK Pressed in HTML");
	window.KeyboardMaestro.Submit('OK');
	}
</script>
</body>
</html>

The window is displayed properly:
image

When I click the radio button it shows up as selected.
When I click the "OK" button the window closes.
But when I look at the outcome, while testvar and buttonvar are set, %HTMLResult% is not.
Run the following:

CODE:

Testvar:  %Variable%testvar%
Buttonvar: %Variable%buttonvar%
Return: %HTMLResult%

Here is the result:
image

When I look in the Value Inspector I see this. Token Text %HTMLResult% is reported as "Not Available in Editor."
image

All of this seems straightforward. I've run additional tests (verifying code with the W3Schools try-it editor) and JavaScript seems to work as it should. Tests include putting onclick="window.KeyboardMaestro.Submit('OK')" directly in the button. But I have not recovered an %HTMLResult% value returned by window.KeyboardMaestro.Submit().

What am I doing wrong? Am I right that the return value should be showing up in %HTMLResult%?

Can you upload your actual "tester" macro? Because when I make a two-action macro using your "Prompt" and "Display Text" code I do get an %HTMLResult% of "OK" returned.

That was with both KM 10.0.x and then with updated v10.1.1, in case something had changed.

@Nige_S
Apart from initializing testvar and buttonvar prior to execution of the custom HTML, what I showed were the only actions present in the macro.

Macros attached:

Under Construction 1.kmmacros (26.4 KB)
Under Construction 5.kmmacros (27.1 KB)

What version of macOS are you running? I am running Monterey 12.3.1 with KM v10.1. I will go ahead and upgrade to 10.1.1 and see if anything changes.


Whoops. I inadvertently gave you a version of the macro that launches the HTML with a subroutine trigger. I was even playing with things like that. But the results are the same, regardless.

jeff,
just in case, check if HTMLResult has become a variable and if so remove that variable, and see if it works.
image

@macdevign_mac
Thanks for the suggestion, but no joy:

image

image

image

@macdevign_mac @Nige_S @peternlewis
I upgraded to 10.1.1. No change.
I wonder again about the macOS version...?

Just to confirm, you have checked that HTMLResult does not exist as variable in "Preference: Variable" screen ? Token should not be used with prefix %Variable%

OK... This is bizarre (and undocumented). Had there been a variable named HTMLResult, then %Variable%HTMLResult% would have found it.

And when I look at the Preference: Variable screen, there is no variable named HTMLResult.

There is, however, a variable named "HTML Result Button" that does contain the value returned by window.KeyboardMaestro.Submit().


image
image

So I will stop trying to use %HTMLResult% and starting using %Variable%HTML Result Button%!

Thanks for the suggestion. But... still odd.

And... the problem generalizes.

When I run a Prompt for User Input action the name of the last button shows up in the deprecated %Variable%Result Button%. It does not show up in the %PromptButton% token.

I wonder how many other tokens are not being set. Some are. For example I routinely use %Application%1% and it works just fine.

@JeffHester -- your second macro worked for me after I added the "Display text" action at the end of it.

From the Wiki:

The %HTMLResult% token (v8+) returns the result of the last Custom HTML Prompt action in this execution instance.

(Emphasis mine.)

If you want to use the result outside that execution instance, eg another macro, you'll have to save it as a global variable (or pass it on as a parameter to a subroutine).

Edit to add...
A quick lock at some other tokens suggests that some old "special variables" are now executing instance specific tokens, which is what might be tripping you up. See Alert Button and Prompt Button for other examples.

1 Like

Ah ha! That is the answer!

And now that I think about it it makes perfect sense. One might launch multiple windows, leaving the actual source of %HTMLReturn% ambiguous. That is doubtless also why the variable %HTML Result Button% was deprecated. (Peter remains far more clever than the rest of us. I would not want to consider going back to a pre-KM existence. :wink: )

Although... I tend to want to open a custom HTML, let it stay open, talk to it, set things with it in real time, and then do things based on status after the window has finally closed. Typically I will set variables with window.KeyboardMaestro.SetVariable(), and those update in real time just fine. I don't know that I've actually used the return value from window.KeyboardMaestro.Submit() before.

So your solution works, so long as you don't call the Custom HTML action asynchronously, which is a reasonable thing to want to do. For example the same macro might want to launch a Custom HTML window and then talk to it with Execute a JavaScript in Custom Prompt or by monitoring variables that the window might change. That requires the window to run asynchronously.

Custom HTML windows do run asynchronously just fine. Consider. The following launches the custom HTML asynchronously:

Needless to say %HTMLResult% doesn't return anything.
Now run the following.

The result is what you would expect. The HTML window hasn't done anything.
image

Now click the radio button in the HTML window. The button responds to the action with onclick="window.KeyboardMaestro.SetVariable('buttonset','Set by SetVariable')"

Run the print code again, and life is good. The window.KeyboardMaestro.SetVariable() call did what it should:
image

Now hit OK and look at the variables again.
image

Values are returned from the <input> statement and the final SetVar() called along with Submit. But now neither %HTMLReturn% nor %Variable%HTML Result Button% is set. Setting name and value in the submit button also fails.

OK. Here is safe practice:

  • Define function KMInit() to use window.KeyboardMaestro.SetVariable() to initialize an exit status variable with a name that includes the window title or the value of data-kmwindowid to "".

  • Define some function that is called by the SUBMIT button with onclick. That function should set the above-mentioned exit status variable and then call windowKeyboardMaestro.Submit(). The easy way to do this would be for various "submit" buttons to pass status as an argument to the function; one close window function with multiple possible submit points, each reporting a unique status.

  • Define function KMWillCloseWindow() to set the variable to whatever you want your exit status to be if the window is closed with windowKeyboardMaestro.Cancel() or by clicking the red button in the corner of the window.

  • Don't try putting name and value arguments in the button that calls the function that calls Submit; it doesn't work.

  • Ignore %HTMLResult% and %Variable%HTML Result Button%, since the above works whether the window is run synchronously or asynchronously. Make the above a habit regardless.

Note: You can also define or redefine functions from an Execute a JavaScript in Custom Prompt action. Very sophisticated asynchronous status and control windows are possible.

Yes, the HTMLResult token is instance-specific, so it is not available outside the instance (which includes being not available at all if the prompt is asynchronous).

If the prompt is asynchronous, then you have to communicate in a different manner, with all the possible issues that may be caused by that, in particular dealing with what happens if the macro is run twice.

The HTMLResult token works around these problems when the prompt is synchronous, since even if the macro is called twice, both prompts will return their results to the appropriate macro regardless of which prompt finishes first.

1 Like

Hi Peter,

Understood completely. As I mentioned above, once I really thought about it I appreciated why you set it up the way that you did. For synchronous uses it makes perfect sense. No criticism intended. The deeper I dig into KM the more impressed I become. Every user's needs are different, but there have been very few times with KM that I haven't been able to accomplish what I set out to do. It has qualitatively changed the way that I interact with my digital world.

If/when I run into the problem of multiple copies of the same window I'll do something like randomize (or serialize) the value of data-kmwindowid to keep them straight. But for now, I have greater use for
custom html windows that are asynchronous. Instead of opening a window to get some information then closing it, a window sits there, providing information and control over something that is ongoing. A second asynchronous macro can poll relevant variables every so often and update the display and/or other things accordingly.

For the project I'm working on I think that I will use the approach to synch an HTML window and a dictionary that other macros can check and modify. I could use JSON to save and restore different configurations... Hmm... Anyway, exit status is seldom an issue; when I close a window it's usually because I just don't need it anymore (which is why I haven't tripped over this before).

In the scheme I described above, finding that the status variable is empty is enough to decide not to launch a duplicate.

So for me, personally, it makes sense to get into the habit of taking more direct responsibility for the handshaking. It costs little but some copied and pasted code, and makes some interesting things possible. Having thought about it more carefully than I had previously, it's going to be fun.

Cheers!

2 Likes

Web forms are usually transactional -- nothing happens server-side until you hit the submit button, then it all happens.

You're into web app territory, so best to assume responsibility for everything and not use standard form functions such as submit or reset at all.

I've a feeling you're going to be pushing boundaries on this, and look forward to seeing what you achieve!

Web apps are precisely what I’m playing with. I first wrote something that might be considered a web app about a year ago, but have gotten more serious about it recently.

One thing that I’m working on at the moment is a universal copy/paste/save/app configuration app. The idea is that a single hot key will copy all available information from any front app and any selections made. Then that information can be pasted in a host of different ways. (In particular into Obsidian, where I also need to jump around among a bunch of saved configurations.) Doing that effectively requires configuration both on the copy side and the paste side. It is also useful to know at a glance what information was captured.

I’ve been doing that so far with variables, conflict palettes, the value inspector, a clipboard editor for both images and text (a fun little project in its own right), and so on. (I’ve also been using Touch Portal, which turns a spare iPad into a wildly more capable alternative to a Stream Deck.) The complexity of the system is starting to overwhelm me, and there is a lot of friction and need for deep knowledge about what is going on. It is useless to anyone else, and would doubtless become useless to me as time passes and I forget details.

So I’m moving in the direction of using a single standard dictionary to house everything and synchronizing its contents with a status/control panel. Different settings can then be saved by moving settings between the dictionary and JSON objects.

In addition to my own needs, my hope is to put together a clean enough and customizable interface for someone who is not a coder to get use out of. After a career in astrophysics I took early retirement a few years ago. These days I work as a coach/consultant/thinking partner for professionals of various sorts. Not uncommonly those conversations involve efficiency of workflows that I have tackled for myself, and I am somewhat evangelical about KM. But not many people have the time or inclination to dive into the deep end. So I’m playing with the idea of offering clients added value in the form of apps that streamline their workflows.

I could do that with Xcode and Cocoa, but KM is wildly more efficient. Peter has already done the heavy lifting. Anyway, we’ll see how that goes!

Back to the original question, my interest in submit and %HTMLResult% was to notify the world that the window had closed, and how to land things smoothly. A submit button could also be used to say, "I'm confused; time to reinitialize." But all of that would have to be handled asynchronously anyway. It doesn't matter whether I'm monitoring %HTMLResult%, %Variable%HTML Result Button%, or some other variable that I set with window.KeyboardMaestro.SetVariable(). %HTMLResult% works wonderfully if you are just waiting for a form to be submitted, but in retrospect it (by design) plays no role in what I am talking about.

Or maybe it does? I suppose that there is nothing that would keep me from launching the custom HTML synchronously, talking to it as if it were asynchronous window, and then doing the cleanup when the Custom HTML action terminated. That would guard against the HTML window closing/crashing in some unexpected way that was not anticipated or properly flagged. Basically I'd be using it as an interrupt, which is what it is anyway. Hmmm...

The tall pole in the tent might be making sure that only one thing is trying to read/modify the dictionary or console at a time. Back in the day I wrote a bunch of instrument control software, but that was on a system (Vax/VMS of all things) that was very good at handling real-time interrupts. Using semaphores is a possibility, although even there it would probably be better to manage things myself. I suppose that I'm talking about a KM "daemon" to play traffic light and requiring any code that wants to modify the dictionary or console to wait until the light is green. Even so, there is enough overhead in KM that I'm sure there will be occasional cases when macros disagree on who has the right of way. Anything that I handed to someone else would need to be able to handle such things gracefully.

OK. I'm just thinking out loud. I'll definitely post as I see how far I can push it!