Skip to main content
Inspiring
April 7, 2023
Answered

How to record javascript dialog input in Action?

  • April 7, 2023
  • 4 replies
  • 3478 views

Hello, all!

 

I have a javascript for Photoshop that displays a dialog at launch, asking for a text string. When I make an action running that script, I'd like the action to also record the text string inputed in the dialog. I've read elsewhere on this forum that this should be possible if you register your script as a plugin, which I tried to to like by including this in the script:

 

/*
@@@BUILDINFO@@@ PoserFrames.jsx 3.0
*/
/*
// BEGIN__HARVEST_EXCEPTION_ZSTRING
<javascriptresource> 
<name>Poser Frames</name> 
<menu>automate</menu>
<enableinfo>true</enableinfo>
<eventid>f35c20c1-2a5c-45d2-98e2-fead0d2bc8c3</eventid>
<terminology><![CDATA[<<  /Version 1
	  /Events <<
		/f35c20c1-2a5c-45d2-98e2-fead0d2bc8c3 [(Poser Frames) /imageReference <<
		  /Recipe [($$$/Actions/Key/PoserFrames/Recipe=Recipe) /uint]
		>>]
	  >>
  >> ]]></terminology>
</javascriptresource>
// END__HARVEST_EXCEPTION_ZSTRING

 

Alas, no dialog input is recorded with the action. Has someone any idea where I'm going wrong?

 

/Joakim

This topic has been closed for replies.
Correct answer jazz-y

 

/*
// BEGIN__HARVEST_EXCEPTION_ZSTRING
<javascriptresource> 
<name>Poser Frames</name> 
<menu>automate</menu>
<enableinfo>true</enableinfo>
<eventid>f35c20c1-2a5c-45d2-98e2-fead0d2bc8c3</eventid>
<terminology><![CDATA[<< /Version 1
                       /Events <<
                       /f35c20c1-2a5c-45d2-98e2-fead0d2bc8c3 [(Poser Frames) <<
                       /recipe [(Recipie text) /string]
                       >>]
                        >>
                     >> ]]></terminology>
</javascriptresource>
// END__HARVEST_EXCEPTION_ZSTRING
*/

var isCancelled = false;
main()
isCancelled ? 'cancel' : undefined

function main() {
	if (!app.playbackParameters.count) {
		//normal run (from scripts menu)
		var result = displayDialog();
		if (!result || result == '') { isCancelled = true; return } else {
			var d = new ActionDescriptor;
			d.putString(stringIDToTypeID('recipe'), result)
			app.playbackParameters = d;
		}
	}
	else {
		var recipe = app.playbackParameters.getString(stringIDToTypeID('recipe'));
		if (app.playbackDisplayDialogs == DialogModes.ALL) {
			// user run action in dialog mode (edit action step)
			var result = displayDialog(recipe);
			if (!result || result == '') { isCancelled = true; return } else {
				var d = new ActionDescriptor;
				d.putString(stringIDToTypeID('recipe'), result)
				app.playbackParameters = d;
			}
		}
		if (app.playbackDisplayDialogs != DialogModes.ALL) {
			// user run script without recording
			alert('variable recordered in action:\n' + recipe);
		}
	}
}

function displayDialog(thisRecipe) {
	var dialog = new Window("dialog");
	dialog.size = [500, 150];
	dialog.text = "Run Poser Frames with recipe";
	dialog.orientation = "column";
	dialog.alignChildren = ["left", "top"];
	dialog.spacing = 10;
	dialog.margins = 20;


	dialog.statictext1 = dialog.add("statictext", undefined, undefined, { name: "label" });
	dialog.statictext1.text = "Your recipe:";
	dialog.statictext1.alignment = ["fill", "top"];

	dialog.edittext1 = dialog.add("edittext", undefined, undefined, { multiline: true });
	dialog.edittext1.alignment = ["fill", "top"];
	dialog.edittext1.size = [400, 50];
	dialog.edittext1.text = thisRecipe ? thisRecipe : '';

	var submit = dialog.add("button", undefined, undefined, { name: "submit" });
	submit.text = "Run Poser Frames!";

	dialog.submit.onClick = function () {
		thisRecipe = dialog.edittext1.text;
		dialog.close();
	};

	dialog.show();

	return thisRecipe;
}

 

* Photoshop registers your eventid on initialization. That is, the script must be in the presets folder at the time of launching Photoshop.

** working with variables written in the terminology section is not possible from the debugger (Photoshop does not record  variables to the action, cannot read them from the action, since accesses the script by eventid). You need to either understand how it works, or or use your imagination by editing the script directly in the presets folder and displaying debugging information with alerts or through the console.

4 replies

Inspiring
April 10, 2023

I'm curious about this one but I'd like more info if possible. Can you run me through a generic example of what you're hoping to accomplish?

You say a dialog comes up asking for some text input. You want to use this elsewhere duing the running of the action. Is this place where it's used elsewhere also within a script that is called in a later step in the action?

 

Step 1: Run "GatherInfo.jsx"

Step 2: Change mode to RGB

Step 3: Add Adjustment Layer: B&W.....Settings....

Step 4: Run "Change Adjustment Layer Name to String from 'GatherInfo.jsx'"

 

Obviously just a made up example, but is that what you're trying to do?

hertzeAuthor
Inspiring
April 10, 2023

Hi! No, what I want to accomplish is simpler than that, I think.

 

My script renders fake film negative borders, like when you have your real film scanned with borders. It is possible to create quite a few looks by changing settings (coded as variable declarations) at the top of the script. Today, the only way for users to change those settings is to open the script and change those variable declarations. I was hoping to find a way to let users change those settings without opening the script.

 

So I’m thinking something like this:

 

1. When the user runs the script from the script menu (or automate menu) it displays a dialog asking for a single text string (containing settings in a specified format).
2. That text string is then exploded and used as user settings (overriding the hardcoded ones) when the rest of the script runs.

 

As I understand it, if the script is coded as a plugin, an Action should be able to record that text string during creation and then **not** display the dialog again when the action later runs. This way you could create multiple actions, with different script settings, from the one script.

Inspiring
April 10, 2023

Do you have to use an action or can you just use the script from start to finish? If all you need to do is override those settings in the script, you can have the dialog open, user inputs their preference settings, they click OK, the script can take that dialog input and set those settings to the desired values. The hardcoded values would have to be converted into variables but it shouldn't be too hard to do.

 

For what it's worth, you could get a bit fancier. Convert the hardcoded values to variables and use a popup dialog to select each setting and even save favorite settings for later recall. 

jazz-yCorrect answer
Brainiac
April 8, 2023

 

/*
// BEGIN__HARVEST_EXCEPTION_ZSTRING
<javascriptresource> 
<name>Poser Frames</name> 
<menu>automate</menu>
<enableinfo>true</enableinfo>
<eventid>f35c20c1-2a5c-45d2-98e2-fead0d2bc8c3</eventid>
<terminology><![CDATA[<< /Version 1
                       /Events <<
                       /f35c20c1-2a5c-45d2-98e2-fead0d2bc8c3 [(Poser Frames) <<
                       /recipe [(Recipie text) /string]
                       >>]
                        >>
                     >> ]]></terminology>
</javascriptresource>
// END__HARVEST_EXCEPTION_ZSTRING
*/

var isCancelled = false;
main()
isCancelled ? 'cancel' : undefined

function main() {
	if (!app.playbackParameters.count) {
		//normal run (from scripts menu)
		var result = displayDialog();
		if (!result || result == '') { isCancelled = true; return } else {
			var d = new ActionDescriptor;
			d.putString(stringIDToTypeID('recipe'), result)
			app.playbackParameters = d;
		}
	}
	else {
		var recipe = app.playbackParameters.getString(stringIDToTypeID('recipe'));
		if (app.playbackDisplayDialogs == DialogModes.ALL) {
			// user run action in dialog mode (edit action step)
			var result = displayDialog(recipe);
			if (!result || result == '') { isCancelled = true; return } else {
				var d = new ActionDescriptor;
				d.putString(stringIDToTypeID('recipe'), result)
				app.playbackParameters = d;
			}
		}
		if (app.playbackDisplayDialogs != DialogModes.ALL) {
			// user run script without recording
			alert('variable recordered in action:\n' + recipe);
		}
	}
}

function displayDialog(thisRecipe) {
	var dialog = new Window("dialog");
	dialog.size = [500, 150];
	dialog.text = "Run Poser Frames with recipe";
	dialog.orientation = "column";
	dialog.alignChildren = ["left", "top"];
	dialog.spacing = 10;
	dialog.margins = 20;


	dialog.statictext1 = dialog.add("statictext", undefined, undefined, { name: "label" });
	dialog.statictext1.text = "Your recipe:";
	dialog.statictext1.alignment = ["fill", "top"];

	dialog.edittext1 = dialog.add("edittext", undefined, undefined, { multiline: true });
	dialog.edittext1.alignment = ["fill", "top"];
	dialog.edittext1.size = [400, 50];
	dialog.edittext1.text = thisRecipe ? thisRecipe : '';

	var submit = dialog.add("button", undefined, undefined, { name: "submit" });
	submit.text = "Run Poser Frames!";

	dialog.submit.onClick = function () {
		thisRecipe = dialog.edittext1.text;
		dialog.close();
	};

	dialog.show();

	return thisRecipe;
}

 

* Photoshop registers your eventid on initialization. That is, the script must be in the presets folder at the time of launching Photoshop.

** working with variables written in the terminology section is not possible from the debugger (Photoshop does not record  variables to the action, cannot read them from the action, since accesses the script by eventid). You need to either understand how it works, or or use your imagination by editing the script directly in the presets folder and displaying debugging information with alerts or through the console.

hertzeAuthor
Inspiring
April 15, 2023

@jazz-y I think you just saved my life! This is exactly what I need. I'm grateful beyond words for this!

c.pfaffenbichler
Community Expert
April 8, 2023

@Paul Riggott provided something concerning persistentSettings more than a decade ago that still seems to work. 

If one runs the Script it provides an alert that counts up across multiple runs. 

// need to initialize the custom settings option in javascript, in flex the try/catch isn't enough to prevent an error for some reason.
var persistentSettings;
try {
persistentSettings = app.getCustomOptions("my_settings_key");         
} catch(e) {};
//
/*if (persistentSettings == null) {
persistentSettings = new ActionDescriptor();
persistentSettings.putData(0," ");
app.putCustomOptions("my_settings_key",persistentSettings,true);
};*/
//
// define document;
//var myDocument = app.activeDocument;
if (!persistentSettings) {var theNumber = 1}
else {var theNumber = persistentSettings.getData(0)};
alert (theNumber);
theNumber++;

persistentSettings = new ActionDescriptor();
persistentSettings.putData(0, theNumber);
app.putCustomOptions("my_settings_key", persistentSettings, true);

 

hertzeAuthor
Inspiring
April 8, 2023

Thanks! I'll look into if that might work as a solution for me!

Stephen Marsh
Community Expert
April 8, 2023

@hertze – This has been on my "to do" list, as I haven't done this before... So I can't help from first-hand experience.

 

1) Is the GUID/UUID unique (not conflicting with any other script currently installed)

 

2) As you didn't post the full code, are you using scriptUI for the interface?

 

EDIT: You might find the following to be helpful - https://www.davidebarranca.com/2012/11/action-recordable-scripts-in-photoshop/

 

hertzeAuthor
Inspiring
April 8, 2023

1) Yes, I used an oline UUID generator, so it should be unique.

 

2) Yes, I tried dipping my toes in scriptUI for the dialog. I used the following code:

 

function displayDialog() {
	
	
	var dialog = new Window("dialog"); 
	dialog.size = [500, 150];
	dialog.text = "Run Poser Frames with recipe"; 
	dialog.orientation = "column"; 
	dialog.alignChildren = ["left","top"]; 
	dialog.spacing = 10; 
	dialog.margins = 20; 
	
	
	dialog.statictext1 = dialog.add("statictext", undefined, undefined, {name: "label"}); 
	dialog.statictext1.text = "Your recipe:"; 
	dialog.statictext1.alignment = ["fill","top"]; 
	  
	dialog.edittext1 = dialog.add("edittext", undefined, undefined,{ multiline: true });  
	dialog.edittext1.alignment = ["fill","top"];
	dialog.edittext1.size = [400, 50];
	  
	var submit = dialog.add("button", undefined, undefined, {name: "submit"}); 
	submit.text = "Run Poser Frames!"; 
	
	dialog.submit.onClick = function() {
		var thisRecipe = dialog.edittext1.text;
		dialog.close();
		alert(thisRecipe);
	};
	
	
	dialog.show();
	
	
}

 

I actually came across David Barranca's 2012 article, but hoped there was a simpler way. I can't claim to fully understand how to adapt his example code for my purposes, but it would require significant changes to the flow of my rather large script, which I'm hoping to avoid...

 

The full script is on GitHub: https://github.com/hertze/PoserFrames/tree/dev-UI

hertzeAuthor
Inspiring
April 8, 2023

It's the file named "Poserframes.jsx" I should add!