How to build dynamic dropdown list in HTML prompt from a single variable

Howdy folks! I finally delved into the HTML prompt and trying to learn some HTML last night. So far it's been going well. But I have inevitably run up against something that has me stumped. Unfortunately due to my complete lack of HTML knowledge, I haven't had any success in searching for an answer because I'm not sure what exactly to search for.

Some of you might be aware of my Typinator macros, a couple of which use AppleScript to build a list of any installed sets, saving that information to a variable with each list name separated by a line separator. This allows me to use that variable to pre-populate a dropdown menu with each set name.

I would like to accomplish the same thing in an HTML prompt... have a dropdown list pre-populated with items stored in a variable. I have tried several things that haven't worked but am at a loss as to how to do it. Below is a copy of the macro I am working on so you can see what I'm currently trying (I'm basically trying to copy the prompts from my Typinator macro just to get some practice).

EDIT: I've also tried the following line for the menu but it doesn’t work either:

<option name="local__Set_Name" value="local__Set_Name"></option>

01)Scratchpad.kmmacros (10 KB)

Macro screenshot (click to expand/collapse)

I'm not 100% sure of which part you need help with. But do a Google search for "javascript fill select options" and see if that helps.

Hey Dan, that's part of the reason I think I was having difficulties searching for an answer because I don't really know how to explain it well since I'm just starting off with HTML. :sweat_smile:

Basically I want to mimic what the Set Name list contains in the Prompt for User Input action in the Set Name list in my Custom HTML Prompt action. But I don't know how to convert a list into something that HTML can read. See my screenshots to see what I'm referring to. Note that in the custom HTML screenshot I modified the source code to include those set names manually so I could keep working on it while I try to figure out the rest.

Prompt For User Input screenshot (click to expand/collapse) (click to expand/collapse)

Custom HTML Prompt screenshot (click to expand/collapse) (click to expand/collapse)

I'll do a Google search for what you mentioned though and see what I come up with. Thanks Dan!

I do that a lot in various ways (Perl, JavaScript), building the options for a select and dropping that into the HTML prompt with JavaScript. You do have to understand how to create a Select.

Rather than describe the process here, I'll just point you to Macro Reporter Macro (for a complex JavaScript example) and A Few Favorites Macro (for a simpler Perl example).

If you run those macros, right click on the prompt to Inspect Element and see the HTML the code creates.

1 Like

Oh I think I understand. The term "Set Name" was confusing me, because I thought "set" was a verb, not a noun, like you wanted to "set the name".

The following will work, but we have more to discuss once you get this working. In your HTML script:

1: Remove the line with %Variable%debug__Set_Name%. You can't use KM variables like this in the script of a Custom HTML Prompt.

2: Add this before </head>:

<script type="text/javascript">
	function KMWindow() {
		let select = document.getElementById("setName");
		select.innerHTML = document.kmvar.debug__SetName;
		return "SCREEN(Main,Left,40%),SCREEN(Main,Top,40%),600,600";
	}
</script>

3: Remove the data-kmwindow from the <body> element, so it's just <body>. You can ask "why" later.

4: Then run it. It should work.

Let me know.

1 Like

I assumed I couldn't but I was trying the shotgun approach and seeing what would stick :laughing:

I'm assuming that’s because it looks like you included that bit in the JavaScript portion.

Working like a charm! This opens up so many opportunities for me, thank you Dan! What else did we need to discuss?

Thank you for the references to those macros. I had indeed inspected the HTML in some other folks macros that I've downloaded but they were too complex for me to wrap my head around. I'll take a look at these!

That's the way we all do it. :slight_smile:

I'm assuming that’s because it looks like you included that bit in the JavaScript portion.

Yes. And I didn't realize you couldn't have both, and the javascript wasn't working, and it took me a while to figure it out.

Working like a charm! This opens up so many opportunities for me, thank you Dan!

Awesome, and you're welcome.

What else did we need to discuss?

The problem with this method is that the values you put in the <option>s might contain HTML characters, which won't work out so well. So, you could either escape them for HTML, or you could pass the values in JSON format, and add some code to handle that in javascript.

I recommend the second way, and I'll post a short example in a little bit. It's a little more complicated, but it's the more "correct" way to do it.

1 Like

What's the format that comes back from your AppleScript code? It looks like it's a pipe-delimited list. Is that right?

Yes it comes back pipe-delimited!

You probably figured this out already, but I had removed the space in your variable name debug__Set Name for the same reason you mentioned in one of your prior posts - I was throwing stuff at a problem to see what fixed the problem. In the previous javascript, I forgot to change it back. But I changed it back in this new code.

So just get the AppleScript result into your variable debug__Set Name, and you don't need to do anything else. The rest is handled in this new javascript

Replace the javascript in the previous post with this:

<script type="text/javascript">
	function KMWindow() {
		// Get a reference to the "select" element.
		let select = document.getElementById("setName");

		// KM variables are stored in "document.kmvar".
		// If the variable name contains a space, the space
		// is replaced with an underscore.
		let data = document.kmvar.debug__Set_Name;

		// I use the "split" function to split the string
		// into an array, separating each item by the
		// specified character, which in this case is "|".
		//
		// After the "split" function is done, I'm using
		// "chaining" to pass the result to the "filter"
		// function, to remove blank items.
		//
		// The result of all that is put in "items".
		let items = data.split("|").filter(s => s != "");

		
		// This loops through each item in the array.
		//
		// For each item, I create an "option" element.
		//
		// Then I set the "text" property to the value of the
		// item. If the item contains any HTML characters,
		// they are automatically "escaped" so they display
		// properly.
		//
		// Then I add the option to the select element.
		items.forEach(item => {
			let option = document.createElement("option");
			option.text = item;
			select.add(option);
		});

		return "SCREEN(Main,Left,40%),SCREEN(Main,Top,40%),600,600";
	}
</script>

I added comments to help you learn what I did. Feel free to ask questions if you want or need to.

1 Like

Hey Dan! Thanks again for your continuing help. I made those adjustments you shared and it works except the first entry is blank... I am no doubt doing something wrong.

I did notice you had adjusted the variable name. That has actually become irrelevant since I since changed all variables I will use in my HTML prompt to the following format: HTMLsetName etc., that way I don't have to deal with spaces, and it makes them easy to clean up afterwards with an AppleScript to delete any variables prepended with HTML.

Anyhoo, the Typinator set names are retrieved and placed in the dropdown menu, but again, the first one is blank for some reason. Below is the complete macro if you want to take a look at it. No rush!

01)Scratchpad.kmmacros (72 KB)

Macro screenshot (click to expand/collapse)

Glad it's working for you.

The blank item is from an "option" you left in the HTML.

If I were you, I'd be using local variables so I didn't have to delete them. Local variables work just fine with a Custom HTML Prompt.

Well it's confirmed, I'm a bonehead. :laughing:
I took that out and it works great!

Initially I ran into issues using local variables...but I can't remember what they were now. No doubt some improper syntax on my part. But I’ll look into it again. Thanks a bunch Dan!

1 Like