How can I pass selected text to a user macro parameter?
Asked by Brock Winstead:

I have a user macro that ideally would take as one parameter the text that the user has selected in the editor. I know that many macros added via the macro browser will take the user's selection and turn it into the body of the macro, e.g. wrapping an excerpt macro around it. Is there a way to fill one parameter, instead of the body, with the user's selected text?

In other words, my ideal situation would be something like:

## [@Param](/t5/user/viewprofilepage/user-id/1345631) text:title=Text\|type=string\|required=true\|desc=Body text\|default=\[some way of accessing the text selected by the user in the editor\]


Answers:
author: Brock Winstead
body: I answered my own question, but ended up answering a couple of other questions along the way. It's not possible to define the user macro itself to pull the selection into a parameter. But!

What I *really* wanted to do was create a custom button on the editor toolbar that opened the macro browser and fed any selected text to the first parameter of my user macro. I don't have to ability to do the kind of plugin development that would "properly" add a button to the toolbar, so I had to resort to JavaScript hacks to make it all happen.

I'll leave out the JS that adds the custom button to the editor toolbar (basically: use an existing button to create the right HTML, use .after() to put it after an existing button). Here's the click event function that I attach to that custom button, with abstracted values.

```
AJS.$('#id-of-custom-button').click( function(){
  var settings = {};
  settings.selectedMacro = {
    "name":"parametername",
    "schemaVersion":1,
    "body":"",
    "defaultParameterValue":"",
    "params":{
      "param1":AJS.Rte.getEditor().selection.getContent(),
      "param2":""}
  };
  settings.onComplete = tinyMCE.confluence.macrobrowser.macroBrowserComplete;
  settings.onCancel = tinyMCE.confluence.macrobrowser.macroBrowserCancel;
  
  AJS.MacroBrowser.open(settings);
  function setFocus() {
    if (!AJS.MacroBrowser.fields.param2) {
      window.requestAnimationFrame(setFocus);
    } else {
      AJS.MacroBrowser.fields.param2.input.select();
    }
  };
  setFocus();
});

```

Here's the breakdown:

* Create an empty settings object
* Add a selectedMacro object to the settings, with some minimum required items
  * including feeding the value of the currently selected text to the **first** parameter
* Add the standard complete and cancel functions to the settings (which tells the macro browser what to do when you click "Save" or "Cancel", and if not specified, it causes problems)
* Open the macro browser with the constructed settings, which fills the text parameter properly
* Set focus on the **second** parameter, so the user isn't redundantly focused on the pre-filled text parameter. (But the focus setter is wrapped in a function that waits until the macro browser is rendered, because otherwise: problems.)

All of this JS goes at the very bottom of the Main Layout template.

Again, this is just the click event handler. There's some preceding JS that adds the custom button.

So that's one way, at least, to pass selected text into a parameter, not the body, of a macro.

P.S. My user macro has two required parameters. If it had only one required parameter, it would be possible to use a different MacroBrowser function to insert it immediately on button click.

comments: author: Bill Bailey
body: Well you might be surprised that that there is the ability to turn/package a user macro into a plug in (uses the same macro code, with some reworking). And within the same atlassian-plugin.xml file, you can add links to your macro in the insert macro menu.

For example, here is the Insert menu with two of my user macro (table title and figure title added)

![Screenshot_2019-06-25 Edit - super test - test - MarketCom Wiki.png](https://community.atlassian.com/t5/image/serverpage/image-id/58708i0C3512E3DAB37511/image-size/large?v=v2&px=999 "Screenshot_2019-06-25 Edit - super test - test - MarketCom Wiki.png")

This is a much cleaner solution and a good way to package user macros.

You can start here:

<https://developer.atlassian.com/server/confluence/user-macro-module/>


author: Brock Winstead
body: That's exactly what I was referring to when I wrote
> I don't have to ability to do the kind of plugin development that would "properly" add a button to the toolbar, so I had to resort to JavaScript hacks to make it all happen.

Cleaner, yes, but outside of what I have access to. Because I don't want it in the macro list menu. I wanted an actual button in the editor toolbar, right up there next to bold, italic, etc.


author: Bill Bailey
body: Ah, but my point is I am stupid and was *still* able to do it. ;-) You just need to do the one tutorial on plugin development to get your environment set, and the community can help with questions.


author: Bill Bailey
body: Still don't see how selecting the text, then inserting the macro won't work. Any selected text is transferred to the body of the macro, which is saved as $body. You can then make the needed parameter equal to $body,


author: Mark MacVicar
body: in Confluence Cloud I was able to do this by highlighting text, typing '{', selecting "Open Macro Browser", and selecting a macro like "No Format".

Sadly, other similar methods of macro selection (e.g., selecting text, then selecting macro from the drop down; or selecting text, typing '{' and typing macro name) didn't work the same, and replaced my highlighted text.


author: Bill Bailey
body: This is a case where there is no documentation, and I had never thought about it as it becomes so automatic when I use macros. It is quite simple: all the selected text is written to the variable $body. You need no parameter at all.

comments: author: Brock Winstead
body: (moved reply to correct location above)


Tags: confluence-server

server