TIP: Custom HTML Prompt to Display Text Large

Hey Neil, the body tag is indeed where you can adjust size and position. I'm sure there's a way to automatically adjust the window location according to it's size, but the only way I would know how to do that is via som KM actions which you could pass via a variable; I do not know how to do that using strictly HTML.

As you're probably aware, first two numbers are location, last two numbers are size. Adjust accordingly until you get the desired result.

If you're interested in passing KM variables to the HTML to set size and location let me know and I can help some more.

<body data-kmwindow="SCREEN(Main,Width)-400,50,350,150">
2 Likes

Right ok thanks. I guess I was perplexed by the fact that the window is centred on all displays regardless of resolution, so I thought there was some auto-alignment going on. Evidently the position has to be set manually. I'll have a play around now. :+1:t3:

Actually, I just found that setting that line of HTML that @cdthomer referenced to the below makes a window twice as big and centred slightly up on the screen. It's the last two numbers that set the size - in this case I typed in 600,300 (the numbers in the original code were 300,150)

<body data-kmwindow="SCREEN(Front,Right)-SCREEN(Front,Width)/2-300,(SCREEN(Front,Height)-500)/2,600,300">

EDIT - sorry I realise I didn't compensate for the width increase affecting the horizontal center in the code I first posted. I've updated the code above. I had originally left the width portion as Width)/2-150 but it seems to have to be Width)/2-300

2 Likes

Awesome! One last question if you don't mind. What exactly do I have to delete to get rid of the onscreen timer without breaking the prompt's autoclose?

Adding hidden to the div tag works for me.

<div id="bottom" hidden>
    Window closes in <span id="counter">3</span>s.
</div>
2 Likes

@cdthomer answered that. I found that removing the text around the Timer and making everything Helvetica keeps it discreetly:

Screen Recording 2022-03-24 at 13.22.14-Animated GIFF 640 12fps

Thanks to @martin for creating this.

1 Like

Thanks!

How do you specify the font as Helvetica? I tried replacing utf-8 with helvetica, but that didn't work.

Incidentally does anyone else find scrolling in a code box in KM a bit maddening? Every couple of scrolls, the macro itself decides to scroll down. Would be great if you could "pop-out" actions with text fields to a long-form view with a resizable window. Just sayin'

1 Like

Add the following line to the style tag:

font-family: helvetica; 

It should then look like so:

<!DOCTYPE html>
<html>

<head>
    <meta charset=utf-8 />
    <style>
        body {
            color: white;
            background: rgba(0, 0, 0, 0.6);
            font-family: helvetica; 
        }

Haha yes, it has frustrated me from time to time as well.

3 Likes
<meta charset=utf-8 />

(The charset attribute is related to the set of characters that are available, and the codes specifiying the point occupied by each character in a table.
Nothing to do with font styling.)

See, for example:

UTF-8 - Wikipedia

1 Like

Do you know if I can activate the prompt and, leave it visible and then dismiss it manually at a later stage in a macro, rather than using an auto-close timer?

Yes. Here are the ideas:

  1. Remove the auto-close timer code. The window will no longer auto-close.
  2. You may
    • add the body attribute data-kmwindowid=your-window-id
      • Example: <body data-kmwindowid="your-window-id"">;
    • then use the following action to close the window in wherever you want in a macro.

Let us know if you need further assistance.

2 Likes

Thankyou. I tried removing various chunks of code one by one but each rendered the code broken. Do you know which bit it is?

Edit: It seems you have to delete

 setInterval(function () {
            countdown();
        }, 1000);

...but not

 function countdown() {
            let i = document.querySelector('#counter');

Hi @noisneil,

You need to remove:

	var timerSwitch = '';
	setInterval(function(){	countdown(); },1000);

and

	function countdown() {
    	let i = document.querySelector('#counter');

		if (timerSwitch != 'pause'){
			i.innerHTML = parseInt(i.innerHTML) -1;
		}
		if (parseInt(i.innerHTML)<=0) {
			window.close();
		}
	}

The 2nd is used by the 1st. If you delete the 1st, there will be no error; it's just that the 2nd is defined but never used. However, if you delete the 2nd without removing the 1st, it will report error because the function used in the 1st--that is the 2nd function--has been removed.

In addition, the following are also timer-related functions.

	function controlTimer(){
		if (timerSwitch == 'pause') {
			timerSwitch = '';
			document.querySelector('#control').innerText = 'Pause Timer';
			document.querySelector('#control').style.color = 'white';
		} else {
			timerSwitch = 'pause';
			document.querySelector('#control').innerText = 'Resume Timer';
			document.querySelector('#control').style.color = 'red';
		}
	}

	function restartTimer(){
		let j = document.querySelector('#counter');
		j.innerHTML = 5;
	}

The above two functions are used by the following two buttons which should be removed at the same time (otherwise, there will be another error report):

		<button type="button" id="restart" onclick="restartTimer()">Restart Timer</button>
		<button type="button" id="control" onclick="controlTimer()">Pause Timer</button>

Finally, the following line has become redundant when no count-down timer is present:

	<p>
		This window will close automatically within <span id="counter">15</span> second(s).
	</p>
2 Likes

Thanks for that. I've deleted the first two code blocks you cited. Neither of the second two blocks are in the code I downloaded from the top post in this thread, so I'm wondering if there's an updated script somewhere that I missed...?

Ah...Sorry.

I was working on a different file. I had several. Some were made for myself use, others I made to share on the forum. I got confused.

I had pause timer / resume timer for that macro, with buttons to activate these functions.

The one I worked on had the following code:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Display Text</title>
    <style>
		body {
			background-color: whitesmoke;
			margin: 10px;
		}
		textarea {
			width: 99%;
			font-size: 16px;
		}
		#buttonDiv {
		  margin-top: 5px;
		  text-align: right;
		}
		button {
			margin-right: 5px;
			width: 91px;
			height: 25px;
			cursor: pointer;
			border-radius: 6px;
			color: white;
		}
		#copy {
			background-color: silver;
		}
		#ok {
			background-color: #008EFB;
		}

		#reload {
		  color: blue;
		}

		p {
			margin-top: 8px;
			text-align:center;
			color:green
		}
		#counter {
			color: red;
		}
    </style>

<script>

	var timerSwitch = '';

	setInterval(function(){	countdown(); },1000);


	function KMInit() {
		window.addEventListener("keydown", function (e) {
		  if (e.keyCode == 13) { // press 'return' to close the window.
			  window.close();
		  }
	    });
  		window.addEventListener("resize", resizeTextArea);
	}
	
	function KMDidShowWindow() {
		resizeWindow();
		resizeTextArea();
		
	}

	function resizeWindow() {
		// get the front screen coordinates: top-lef.X, top-left.Y, bottom-right.X, bottom-right.Y
		let screenCoordinatesArr = window.KeyboardMaestro.ProcessTokens( '%Screen%Front%' ).split(",");
		
		let winSize = window.KeyboardMaestro.GetVariable( 'instanceWindowSize' );
		let winWidth = "";
		let winHeight = "";
		
		
		if (winSize != "") {
			let winSizeArr = winSize.split(",");
			winWidth = parseInt(winSizeArr[0]);
			winHeight = parseInt(winSizeArr[1]);
		} else {
			winWidth = 540;  // Default window width; change the value as you need.
			winHeight = 300; // Default window height; change the initial value as you need.
		}
				
		// the winX below will set the HTML window to the upper-right color of the front window.
		let winX = parseInt(screenCoordinatesArr[0]) + parseInt(screenCoordinatesArr[2]) - winWidth;
		let winY = 19; // 19 is the height of the menu bar.

		window.KeyboardMaestro.ResizeWindow(winX + "," + winY + "," + winWidth + "," + winHeight);
	}
	
	function countdown() {
    	let i = document.querySelector('#counter');

		if (timerSwitch != 'pause'){
			i.innerHTML = parseInt(i.innerHTML) -1;
		}
		if (parseInt(i.innerHTML)<=0) {
			window.close();
		}
	}

	function resizeTextArea(){
		var h = window.innerHeight;
		document.querySelector('#text').style.height = (h - 100) + 'px';
	}

	function copyText(){
		let text = document.querySelector('#text');
		text.select();
		document.execCommand("copy");
	}

	function reloadText(){
		let text = window.KeyboardMaestro.GetVariable( 'DisplayText' );
		document.querySelector('#text').value = text;
	}

	function controlTimer(){
		if (timerSwitch == 'pause') {
			timerSwitch = '';
			document.querySelector('#control').innerText = 'Pause Timer';
			document.querySelector('#control').style.color = 'white';
		} else {
			timerSwitch = 'pause';
			document.querySelector('#control').innerText = 'Resume Timer';
			document.querySelector('#control').style.color = 'red';
		}
	}

	function restartTimer(){
		let j = document.querySelector('#counter');
		j.innerHTML = 5;
	}
</script>

  </head>
  <body>

	The text is:
	<textarea id="text" name="DisplayText">	</textarea>

	<div id='buttonDiv'>
		<button type="button" id="restart" onclick="restartTimer()">Restart Timer</button>
		<button type="button" id="control" onclick="controlTimer()">Pause Timer</button>
		<button type="button" id="reload" onclick="reloadText()">Reload Text</button>
    	<button type="button" id="copy" onclick="copyText()">Copy Text</button>
		<button type="button" id="ok" onclick="window.close()">OK</button>
	</div>

	<p>
		This window will close automatically within <span id="counter">15</span> second(s).
	</p>
  </body>
</html>

And the window looks like this:

image

Sorry about that.

Yes. For the example macro I posted in the first post, you only need to move the 1st and 2nd, plus the following code:

<div id="bottom" hidden>
    Window closes in <span id="counter">3</span>s.
</div>
2 Likes

Thank you for this great macro!

Can someone tell me or show me how to detect when this HTML prompt window is closed? I want to disable the palette that was used to trigger this and then re-enable that palette when the window is gone.

Hi all,

While I, too, was trying to get the hang of HTML prompts, I've simplified Martin's code as fas as possible to understand what's going on.

Here's the code to display the number of words on the clipboard in the upper right corner. First I let KM count them:

%Calculate%WORDS(%CurrentClipboard%)%

then I used this code (sorry, I don't know how to paste code and snippets yet...) for a simple formatted notification


<!DOCTYPE html>
<html>

<head>
 <meta charset="utf-8">
 <style>
	body {
		color: lightgray;
		background-color: rgba(0,0,0,0.7);
		font-family: Helvetica;
		font-size: 30px;
		text-align: right;
		padding-right: 30px;
	}
 </style>
</head>

<script>
	const goAway = setTimeout(bye, 2000); //display for 2 seconds
	function bye() {
		window.close();
	}

	function KMInit() {
	window.addEventListener('keydown', function (event) {
		if (event.keyCode == 27) { //Escape?
			 window.close();
			}
		 });
	 }

	function KMDidShowWindow() {
	const txt = window.KeyboardMaestro.GetVariable('Text to Display');
	document.querySelector('#text').innerText = txt + " wrd";
	 }
</script>


<body data-kmwindow="SCREEN(Front,Right)-500,40,500,60" >
	 <div id="text"> </div>
 </body>


</html>

Hope this helps...

1 Like

How can I pass the window position, height and width, along with the font size via KM variables to the script?

Hi @mikewolf1127,

For passing window height and width, please refer to the post below:

To be more specific, I use a function to resize the window:

	function resizeWindow() {
		// get the front screen coordinates: top-lef.X, top-left.Y, bottom-right.X, bottom-right.Y
		let screenCoordinatesArr = window.KeyboardMaestro.ProcessTokens( '%Screen%Front%' ).split(",");
		
		let winSize = window.KeyboardMaestro.GetVariable( 'instanceWindowSize' );
		let winWidth = "";
		let winHeight = "";
		
		
		if (winSize != "") {
			let winSizeArr = winSize.split(",");
			winWidth = parseInt(winSizeArr[0]);
			winHeight = parseInt(winSizeArr[1]);
		} else {
			winWidth = 540;  // Default window width; change the value as you need.
			winHeight = 300; // Default window height; change the initial value as you need.
		}
				
		// the winX below will set the HTML window to the upper-right color of the front window.
		let winX = parseInt(screenCoordinatesArr[0]) + parseInt(screenCoordinatesArr[2]) - winWidth;
		let winY = 19; // 19 is the height of the menu bar.

		window.KeyboardMaestro.ResizeWindow(winX + "," + winY + "," + winWidth + "," + winHeight);
	}

If the following action is activated, then it will use the number set by you, otherwise, the window size is by default as set in the html code.
image

This gives you some idea how things are handled by javascript functions.

For font size, you can use a javascript function to change it too. You may refer to posts such as

The difference in Keyboard Maestro is that you need to get the KM variable value. This is demonstrated in the code above, such as:

let winSize = window.KeyboardMaestro.GetVariable( 'instanceWindowSize' );