Custom HTML Prompt That Doesn't Need Focus to Click a Button?

@peternlewis I'm not sure how to explain this, but I'll try my best.

So let's say I have a Custom HTML Prompt with a button. When I first click on the button, all that happens is that the Prompt window gets the focus. I have to click a second time to actually get the button to click.

With Palettes, it works differently. Clicking on a button on a palette does not take focus from the current app, and the button gets clicked with only one mouse click.

So is there any way to make a Custom HTML Prompt act like a Palette?

Thanks.

I did a quick test, and the button gets the click straight away.

Ahh, ok, you mean if you click away somewhere else, and then click back to the window, the click back to the window focusses it, but does not act on the clicked item. Yes, that is generally how most windows work.

The behaviour is a feature of the control, not the window, so the button would have to be different in order for it to respond to the click. I'm not sure there is any way to do that.

1 Like

You might be able to do something pretty dodgy using hover on elements. My thinking is that if you click the HTML window then whichever element you’re hovering over could immediately activate, then keyboard maestro could switch back to the previous application.

I don’t recommend this… but it might kindof work

1 Like

Thanks for the idea, but it turns out that hover doesn't happen unless the window has focus, which makes sense. But I truly thank you for thinking of an outside-the-box solution - even if it might have been "dodgy", it was still a cool idea. :smile:

Fortunately, I have a solution, and I'll post it shortly.

I found a solution. And thank you KM (@peternlewis) for allowing me to do this kind of thing from a "browser window" (Custom HTML Prompt):

As I said, if the window isn't currently focused, the first click over the button just focuses the window. So I listen to the focus event.

From there, I call a KM macro using window.KeyboardMaestro.Trigger that checks to see if the left mouse button is down (it probably always is, but it doesn't hurt to check), and whether it's over the button.

If all of that is true, I use an Execute a JavaScript in Custom HTML Prompt to execute the function the button click would have called. (I could have also just called the button's click() method).

For anyone who might want a solution like this, here's some code:

const _titleBarHeight = 16;
const _checkMouseDownOverCancelButtonMacroUUID = "99F97187-DAEC-4C02-89F2-D3841EFE2695";

function KMDidShowWindow() {
	// Delay adding the event listener - we don't need the first "focus" event.
	setTimeout(() => {window.addEventListener("focus", onWindowFocused);}, 100);
}

function onWindowFocused() {
	// If the Cancel button is visible, then call our function,
	// but delay it so this "focus" event finishes processing.
	// NOTE: "isHidden()" is a custom prototype - just use your imagination.
	if (!document.getElementById("cancelButton").isHidden())
		setTimeout(executeCheckMouseDownOverCancelButton, 10);
}

function executeCheckMouseDownOverCancelButton() {
	// build the parameters we'll pass to the KM macro
	var params = {};
	var r = document.getElementById("cancelButton").getBoundingClientRect();
	params.CancelButtonLeft = Math.round(window.screenX + r.left);
	params.CancelButtonTop = Math.round(window.screenY + r.top + _titleBarHeight);
	params.CancelButtonRight = Math.round(params.CancelButtonLeft + r.width);
	params.CancelButtonBottom = Math.round(params.CancelButtonTop + r.height);
	
	var paramString = JSON.stringify(params, null, 2);
	console.log(`Calling "Check Mouse Down Over Cancel Button" using the param\n${paramString}`);
	window.KeyboardMaestro.Trigger(_checkMouseDownOverCancelButtonMacroUUID, paramString);
}

function cancelButtonClick() {
	// code not shown because it's outside the context of this topic
}

Here's the macro that gets called, edited to show only the relevant stuff:

Reference: MACRO: Floating Progress Bar (Custom HTML Prompt) v1.3

4 Likes

Thanks, I think I learned something new here:

It's possible to call a function ( 'cancelButtonClick()' ) from with in a execute action, although the function it self is not defined within the executing script it self.

Is this correct?

Right. The executing script has access to everything in the HTML (DOM) and any JavaScript defined inside it. And yes, this is a very cool and useful thing. :grinning_face_with_smiling_eyes:

1 Like

Great, thank you!!

1 Like