Drop-Down List in a Frame

Discuss macro implementations, ask for macro help (to share your creations, see User Creations, probably either Campaign Frameworks or Drop-in Resources).

Moderators: dorpond, trevor, Azhrei, giliath, jay, Mr.Ice

Fobbo
Giant
Posts: 196
Joined: Wed Feb 01, 2006 2:11 pm

Drop-Down List in a Frame

Post by Fobbo »

Is there away to create a drop-down list of players in a Frame that can be used for input?

I know how to create it in a dialog but not a frame.

If it can't be done is there away to create a large text field in a dialog? I can get an input text field but it is just one line wide.

Thanks
Fobbo

the_meek
Cave Troll
Posts: 99
Joined: Fri Aug 01, 2008 9:18 am

Re: Drop-Down List in a Frame

Post by the_meek »

Frames and dialogs are practically the same thing. Anything you do HTML-wise in one will work in the other.

For the drop down, you'll use select with options:

<select name="test">
<option value=0>0
<option value=1>1
<option value=2>2
</select>

For the large text field, I assume you'd want a textarea:

<textarea name="blah" cols=20 rows=3>Stuff you want to show up in the textarea.</textarea>

I've found that textareas don't work well in Maptool, because it doesn't automatically wrap text and doesn't save the user starting a new line, unless I'm missing something.

Does that help?

Fobbo
Giant
Posts: 196
Joined: Wed Feb 01, 2006 2:11 pm

Re: Drop-Down List in a Frame

Post by Fobbo »

Thank you the_meek, a little bit how would you create the options list of the select? based on the getPlayers function.

User avatar
Rumble
Deity
Posts: 6235
Joined: Tue Jul 01, 2008 7:48 pm

Re: Drop-Down List in a Frame

Post by Rumble »

Fobbo wrote:Thank you the_meek, a little bit how would you create the options list of the select? based on the getPlayers function.
You could do it like this:

Code: Select all

<select name="test">
[r,foreach(player, getPlayers()): "<option value="+player+">"+player+"</option>"]
</select>

User avatar
biodude
Dragon
Posts: 444
Joined: Sun Jun 15, 2008 2:40 pm
Location: Montréal, QC

Re: Drop-Down List in a Frame

Post by biodude »

Oh Rumble, have you forgotten about Wiki: listFormat() again? :wink:

Code: Select all

[R: listFormat( getPlayers(), "<select name='test'>%list</select>", "<option value='%item'>%item</option>", "" )]
 
I find this to be the fastest way to turn a list into an html option list (with a little Wiki: strformat() trickery, you can even return a different value from the one displayed, which is something that's a little harder to do with Wiki: input() ).

Edit: fixed a typo in listFormat :(
Last edited by biodude on Tue Mar 23, 2010 1:34 pm, edited 1 time in total.
"The trouble with communicating is believing you have achieved it"
[ d20 StatBlock Importer ] [ Batch Edit Macros ] [ Canned Speech UI ] [ Lib: Math ]

User avatar
Rumble
Deity
Posts: 6235
Joined: Tue Jul 01, 2008 7:48 pm

Re: Drop-Down List in a Frame

Post by Rumble »

biodude wrote:Oh Rumble, have you forgotten about Wiki: listformat() again? :wink:

Code: Select all

[R: listformat( getPlayers(), "<select name='test'>%list</select>", "<option value='%item'>%item</option>", "" )]
 
I find this to be the fastest way to turn a list into an html option list (with a little Wiki: strformat() trickery, you can even return a different value from the one displayed, which is something that's a little harder to do with Wiki: input() ).
Oh listformat, how I hate you. The instructions on the page are the most cryptic and impenetrable thing I've ever read; I have never used it in a macro, to the best of my knowledge, because I don't understand how. I use strformat() all the time, though.

Granted, your example goes a long way to helping that lack of understanding.

User avatar
Raoden
Dragon
Posts: 381
Joined: Fri Dec 18, 2009 2:33 am
Location: San Diego

Re: Drop-Down List in a Frame

Post by Raoden »

biodude wrote:Oh Rumble, have you forgotten about Wiki: listformat() again? :wink:
Well, considering the wiki page you linked to there is blank and gives no explanation of how to use said function ... :wink:
"Fairy tales do not tell children the dragons exist. Children already know that dragons exist. Fairy tales tell children the dragons can be killed."
- G. K. Chesterton

Wonderful HTML/CSS reference * Color Manager * Token Manager 2.0

User avatar
biodude
Dragon
Posts: 444
Joined: Sun Jun 15, 2008 2:40 pm
Location: Montréal, QC

Re: Drop-Down List in a Frame

Post by biodude »

Raoden wrote:Well, considering the wiki page you linked to there is blank and gives no explanation of how to use said function ... :wink:
oops, typo - it should be 'Wiki: listFormat()" (silly camelCase :oops: ). Edited in original post.
Try again, it's pretty sweet.
"The trouble with communicating is believing you have achieved it"
[ d20 StatBlock Importer ] [ Batch Edit Macros ] [ Canned Speech UI ] [ Lib: Math ]

User avatar
biodude
Dragon
Posts: 444
Joined: Sun Jun 15, 2008 2:40 pm
Location: Montréal, QC

Re: Drop-Down List in a Frame

Post by biodude »

Rumble wrote: Oh listformat, how I hate you. The instructions on the page are the most cryptic and impenetrable thing I've ever read; I have never used it in a macro, to the best of my knowledge, because I don't understand how. I use strformat() all the time, though.

Granted, your example goes a long way to helping that lack of understanding.
Yeah, it took me a while to get comfortable with it, but some more examples might help. Say, I think I'll add "making a drop down list" to said wiki page, since it is perhaps one of the most commonly useful applications.

EDIT: added 2 more exmples (with a long explanation) added to Wiki: listFormat() page. Hope that helps.
"The trouble with communicating is believing you have achieved it"
[ d20 StatBlock Importer ] [ Batch Edit Macros ] [ Canned Speech UI ] [ Lib: Math ]

User avatar
Rumble
Deity
Posts: 6235
Joined: Tue Jul 01, 2008 7:48 pm

Re: Drop-Down List in a Frame

Post by Rumble »

biodude wrote:
Rumble wrote: Oh listformat, how I hate you. The instructions on the page are the most cryptic and impenetrable thing I've ever read; I have never used it in a macro, to the best of my knowledge, because I don't understand how. I use strformat() all the time, though.

Granted, your example goes a long way to helping that lack of understanding.
Yeah, it took me a while to get comfortable with it, but some more examples might help. Say, I think I'll add "making a drop down list" to said wiki page, since it is perhaps one of the most commonly useful applications.

EDIT: added 2 more exmples (with a long explanation) added to Wiki: listFormat() page. Hope that helps.
That example is very helpful. I have many places in which that might speed things up a lot.

User avatar
Raoden
Dragon
Posts: 381
Joined: Fri Dec 18, 2009 2:33 am
Location: San Diego

Re: Drop-Down List in a Frame

Post by Raoden »

biodude wrote:EDIT: added 2 more exmples (with a long explanation) added to Wiki: listFormat() page. Hope that helps.
Yep, that looks quite a bit more useful than it did before (especially the typo'd blank version!). I might have to try this out!
"Fairy tales do not tell children the dragons exist. Children already know that dragons exist. Fairy tales tell children the dragons can be killed."
- G. K. Chesterton

Wonderful HTML/CSS reference * Color Manager * Token Manager 2.0

Fobbo
Giant
Posts: 196
Joined: Wed Feb 01, 2006 2:11 pm

Re: Drop-Down List in a Frame

Post by Fobbo »

Thank you all, that worked out great. I can see the drop down list of connected players in my frame.

This however has opened up a new set of questions, that I am sure you all know the answer to.

What I am looking to do is have a macro send via whisper to a selected player certain token information ie name, race, etc...

This is what I had before and it worked but I didn't like the extracomment text field I wanted a larger text area, so I thought I would change to a frame hence my question before about the player list.

Code: Select all

[h: playerList = getAllPlayerNames() ]

[h: status=input(
"Player|" +playerList+"|Select PC|LIST|SELECT=0",
"extraComment| |Add Extra Comment To Send To Player|TEXT|WIDTH=100 SPAN=TRUE")]
[h:abort(status) ]

[h: targetName = listGet(playerList,Player)]
[h: testString = "You know the following about this creature: " +token.name+ " " +Race]

[h: sendTo = json.fromList(targetName)]

[r: outputTo(sendTo, testString)]
Here is the new code I am attempting to use:

Code: Select all

[h: playerList = getAllPlayerNames() ]

[frame("MKCDC15","width=200;height=300"):{
   <html>
        <head>
             <title>Monster Knowledge Check DC15</title>
        </head>
        <body><form name ="MKCDC15" method="json" action='[r:macroLinkText("MKC DC 15@this","none")]'>
            <table border="0" cellpadding="0" cellspacing="0">
                <tr>
                   <th>
                       Send To <small>([R:macroLink("Refresh Player List", "MKC DC 15@this", "none")])</small>
                   </th>
               </tr>
               <tr>
                 <td>
	[R: listFormat( playerList, "<select name='Player'>%list</select>", "<option value='%item'>%item</option>", "" )]
                 </td>
               </tr>
              <tr><td align="center">
          <input type='submit' value='Send' >
        </td></tr>
</table>
   </html>
}]

[h: targetName = listGet(playerList,Player)]
[h: testString = "You know the following about this creature: " +token.name+ " " +Race]

[h: sendTo = json.fromList(targetName)]

[r: outputTo(sendTo, testString)]
[h:abort(0)]
When I select a token and run a macro that points to this one it brings up the frame but then also input boxes for Player, If I click ok it sends the whisper to the player I have selected in the drop down list. How do I stop the input dialog box from coming up and use the send button?

User avatar
biodude
Dragon
Posts: 444
Joined: Sun Jun 15, 2008 2:40 pm
Location: Montréal, QC

Re: Drop-Down List in a Frame

Post by biodude »

Unlike the input function, frames & dialogs do not interrupt (pause) macro execution. They draw the frame, and then keep on chugging. To use the frame & dialog roll options, you have to change the way you structure your information flow.

So, in your code, the first time the frame is drawn, it continues after and executes the code. Since the variable "Player" does not have a value at this point (the form in the frame has not been submitted), MapTool prompts you for a value.

So, usually, the form in the frame gets submitted to a macro to do something with it. Note that this can be the same macro (as your example does). My favourite way to handle this is zEal's "self-executing" frame. It would look like this:

Code: Select all

[if( json.type( macro.args )!="OBJECT" ), code:{  <!-- Form data not submitted, (re-)draw the frame. -->
   [h: playerList = getAllPlayerNames() ]
   [H: thisMacro = getMacroName()+"@this" ]  <!-- why have to change your code, just because you renamed your macro later? ;-) -->
   [frame("MKCDC15","width=200;height=300"):{
      <html>
           <head>
                <title>Monster Knowledge Check DC15</title>
           </head>
           <body><form name ="MKCDC15" method="json" action='[r:macroLinkText( thisMacro, "none")]'>
               <table border="0" cellpadding="0" cellspacing="0">
                   <tr>
                      <th>
                             Send To <small>([R:macroLink("Refresh Player List", thisMacro, "none")])</small>
                      </th>
                  </tr>
                  <tr>
                    <td>
      [R: listFormat( playerList, "<select name='Player'>%list</select>", "<option value='%item'>%item</option>", "" )]
                    </td>
                  </tr>
                 <tr><td align="center">
             <input type='submit' value='Send' >
           </td></tr>
      </table>
      </html>
   }]
   [h:abort(0)]
};{
   <!-- process form data submitted as a json object (in 'macro.args') -->
   [H: targetName = json.get( macro.args, 'Player' )]<!-- contains the literal value, not an index.  See how much fun html forms can be? -->
   [h: testString = "You know the following about this creature: " +token.name+ " " +Race]
   [h: sendTo = json.fromList(targetName)]
   [H: outputTo(sendTo, testString)]  <!-- this is queued output: it will be sent to chat after this macro stops. -->
}]
 
The macro now contains 2 main sections: one to draw the frame if no form data is submitted (json object), and the second to process submitted form data. This also helps speed up processing, since the macro isn't doing both at the same time. If you want it to re-draw the frame AND process arguments, just take that section out of the IF code block.

Hope that helps.
"The trouble with communicating is believing you have achieved it"
[ d20 StatBlock Importer ] [ Batch Edit Macros ] [ Canned Speech UI ] [ Lib: Math ]

Fobbo
Giant
Posts: 196
Joined: Wed Feb 01, 2006 2:11 pm

Re: Drop-Down List in a Frame

Post by Fobbo »

biodude wrote:Unlike the input function, frames & dialogs do not interrupt (pause) macro execution. They draw the frame, and then keep on chugging. To use the frame & dialog roll options, you have to change the way you structure your information flow.

So, in your code, the first time the frame is drawn, it continues after and executes the code. Since the variable "Player" does not have a value at this point (the form in the frame has not been submitted), MapTool prompts you for a value.

So, usually, the form in the frame gets submitted to a macro to do something with it. Note that this can be the same macro (as your example does). My favourite way to handle this is zEal's "self-executing" frame. It would look like this:

Code: Select all

[if( json.type( macro.args )!="OBJECT" ), code:{  <!-- Form data not submitted, (re-)draw the frame. -->
   [h: playerList = getAllPlayerNames() ]
   [H: thisMacro = getMacroName()+"@this" ]  <!-- why have to change your code, just because you renamed your macro later? ;-) -->
   [frame("MKCDC15","width=200;height=300"):{
      <html>
           <head>
                <title>Monster Knowledge Check DC15</title>
           </head>
           <body><form name ="MKCDC15" method="json" action='[r:macroLinkText( thisMacro, "none")]'>
               <table border="0" cellpadding="0" cellspacing="0">
                   <tr>
                      <th>
                             Send To <small>([R:macroLink("Refresh Player List", thisMacro, "none")])</small>
                      </th>
                  </tr>
                  <tr>
                    <td>
      [R: listFormat( playerList, "<select name='Player'>%list</select>", "<option value='%item'>%item</option>", "" )]
                    </td>
                  </tr>
                 <tr><td align="center">
             <input type='submit' value='Send' >
           </td></tr>
      </table>
      </html>
   }]
   [h:abort(0)]
};{
   <!-- process form data submitted as a json object (in 'macro.args') -->
   [H: targetName = json.get( macro.args, 'Player' )]<!-- contains the literal value, not an index.  See how much fun html forms can be? -->
   [h: testString = "You know the following about this creature: " +token.name+ " " +Race]
   [h: sendTo = json.fromList(targetName)]
   [H: outputTo(sendTo, testString)]  <!-- this is queued output: it will be sent to chat after this macro stops. -->
}]
 
The macro now contains 2 main sections: one to draw the frame if no form data is submitted (json object), and the second to process submitted form data. This also helps speed up processing, since the macro isn't doing both at the same time. If you want it to re-draw the frame AND process arguments, just take that section out of the IF code block.

Hope that helps.
Thank you biodude,

I have tried your code however when I click on the send button it asks me for token.name and race. It then sends what ever was the value in the input pops to the player selected.

The token.name and race should come from the token selected where the macro call was triggered.

For example I have player connected named "Bob"
A monster token called Sneeze and race of Goblin.

When I select the token Sneeze I have a macro on Sneeze
[macro("MKCDC15@Lib:DMTools"):""]

In the frame that pops up I see "Bob" and click on send

Bob should get a whisper with:
You know the following about this creature: Sneeze Goblin

User avatar
biodude
Dragon
Posts: 444
Joined: Sun Jun 15, 2008 2:40 pm
Location: Montréal, QC

Re: Drop-Down List in a Frame

Post by biodude »

Fobbo wrote: Thank you biodude,

I have tried your code however when I click on the send button it asks me for token.name and race. It then sends what ever was the value in the input pops to the player selected.

The token.name and race should come from the token selected where the macro call was triggered.
Right. Good point. Sorry, I didn't fully test before posting (which goes to show the value of bug-checking ;) ). On the bright side, we get to learn something about token focus (or context, as I like to think of is) ;-)

The problem is that once the form is drawn, token focus disappears, so when the form is submitted, the macro has forgotten what the Current Token is. So, when the macro is called again by form submission, there is no current token, regardless of what is selected or impersonated :(
Fortunately, you can tell it what it should be in the Wiki: macroLinkText() function. So, the command that specifies the action for the html form should include the optional argument to specify the token context under which to run the specified macro. With that, it should 'remember' which token is the current one when you submit the form. The code would now look like this (hidden in spoiler to save our collective scrolling wheels):
MonsterKnowledgeCheck

Code: Select all

[if( json.type( macro.args )!="OBJECT" ), code:{  <!-- Form data not submitted, (re-)draw the frame. -->
   [h: playerList = getAllPlayerNames() ]
   [H: thisMacro = getMacroName()+"@this" ]  <!-- why have to change your code, just because you renamed your macro later? ;) -->
   [frame("MKCDC15","width=200;height=300"):{
      <html>
           <head>
                <title>Monster Knowledge Check DC15</title>
           </head>
           <body><form name ="MKCDC15" method="json" action='[r:macroLinkText( thisMacro, "none", "", currentToken() )]'><!-- the form is sent to this macro, output displayed to "none", no arguments, with the current token as focus. -->
               <table border="0" cellpadding="0" cellspacing="0">
                   <tr>
                      <th>
                             Send To <small>([R:macroLink("Refresh Player List", thisMacro, "none")])</small>
                      </th>
                  </tr>
                  <tr>
                    <td>
      [R: listFormat( playerList, "<select name='Player'>%list</select>", "<option value='%item'>%item</option>", "" )]
                    </td>
                  </tr>
                 <tr><td align="center">
             <input type='submit' value='Send' >
           </td></tr>
      </table>
      </html>
   }]
   [h:abort(0)]
};{
   <!-- process form data submitted as a json object (in 'macro.args') -->
   [H: targetName = json.get( macro.args, 'Player' )]<!-- contains the literal value, not an index.  See how much fun html forms can be? -->
   [h: testString = "You know the following about this creature: " +token.name+ " " +Race]
   [h: sendTo = json.fromList(targetName)]
   [H: outputTo(sendTo, testString)]  <!-- this is queued output: it will be sent to chat after this macro stops. -->
}]
  
Is that better?
"The trouble with communicating is believing you have achieved it"
[ d20 StatBlock Importer ] [ Batch Edit Macros ] [ Canned Speech UI ] [ Lib: Math ]

Post Reply

Return to “Macros”